Have a problem. I create my game object like this:
var game_status = {
money : 350000000,
reset_status : function() {
this.money = 350000000;
}
}
function saveGame(){
localStorage.setItem('game_status', JSON.stringify(game_status));
}
function loadGame(){
game_status = JSON.parse(localStorage.getItem('game_status'));
}
After loading game status method "reset_status" doesn't exists anymore.
Probably I should describe object, create instance, save instance, and then loading creating instance anew with parameters from load?
Just assign the stored state to the object:
Object.assign(game_status, JSON.parse(localStorage.getItem('game_status')));
That way you don't have to write a constructor.
Since anyhow object state & object behavior lies within a simple hash and assuming what's needed here is a quick patch, I would do something like:
var INITIAL_GAME = {
money : 350000000
},
game_status;
function saveGame(){
// strip behavior
delete game_status.resetGame;
localStorage.setItem('game_status', JSON.stringify(game_status));
}
function loadGame(){
game_status = JSON.parse(localStorage.getItem('game_status'));
if (!game_status) {
// init by cloning initial object
game_status = JSON.parse(JSON.stringify(INITIAL_GAME));
}
// set behavior again
game_status.resetGame = function resetGame() {
this.money = 350000000;
}
}
loadGame();
for (var attrname in game_statusTemp) { game_status[attrname] =
game_statusTemp[attrname]; }
A quick workaround for my case. Found in
How to duplicate object properties in another object? and How can I merge properties of two JavaScript objects dynamically?
Related
This is probably a stupid question, but is there way in Javascript (ES5 preferred) to "extend" a class function similar to how i can i extend a parent' function in PHP ?
Basicly, i have this class hierarchy from System -> Weapon -> Dual and i would like Dual to use the code from System.setState() and then do some more stuff.
Note i use pre ES6 syntax for my hierarchy.
function System(system){
this.setState = function(){
//do stuff
}
}
function Weapon(system){
System.call(this, system);
}
Weapon.prototype = Object.create(System.prototype);
function Dual(system){
Weapon.call(this, system);
this.setState = function(){ // this is the problem
System.prototype.setState(); // error - not defined
//Weapon.protoype.setState() doesnt work either
//do more stuff
}
}
Dual.prototype = Object.create(Weapon.prototype);
Because setState is an instance property of System it does not exist on System.proptotype so you can't call it using System.prototype.setState.call. If you want to call it in this case, just create an object from System like so
function Dual(system){
Weapon.call(this, system);
var parent = new System(system);
this.setState = function() {
parent.setState(); // done
}
}
Instance properties are duplicated on each individual object ( they don't share). Whereas, prototype properties will be shared among children( they are not duplicated on child classes). To make all System 's subclasses share setState function, add it to System 's prototype
function System (arg) { ... }
System.prototype.setState = function () {...}
Now in your child classes, you can do
function Dual(system){
Weapon.call(this, system);
this.setState = function() {
System.prototype.setState.call(this); // done
}
}
First, you should set your instance methods on the prototype:
System.prototype.setState = function() {
// your stuff
}
This will improve performance and allow you to inherit the method without constructing a System instance.
Then, you just need to call System's version of setState on the right object (the instance of Dual) instead of calling it on System.prototype:
Dual.prototype = Object.create(Weapon.prototype, {
'setState': { value: function(){
System.prototype.setState.call(this) // fixed
// other stuff
}}
})
I have some trouble with getting the name of a method stored in a variable... Here is an exemple of what I want :
Function MyObject(){
this.actualMethod = this.thatName;
}
MyObject.prototype.thatName = function(){}
MyObject.prototype.getActualMethodName = function(){
return this.actualMethod.name; /* This doesn't work since the function itself is anonymous, so this.actualMethod.name doesn't work... I want it to return "thatName" */
}
I tried to navigate through the prototype with my console, in vain... Is there a way to do this ?
You need to name the function:
MyObject.prototype.thatName = function thatName() {};
Or, as you mentioned, you can find its name in the prototype (but I wouldn't suggest you to do it):
for (var key in MyObject.prototype) {
if (MyObject.prototype[key] === this.actualMethod) {
return key;
}
}
But why do you need this? Maybe there could be a better solution.
So, I have a large object called con in that object, I have many variables, numbered sort of like an excel sheet, b19, b20, b21, etc.
I am trying to return a value from each one, but when I do a console log, It logs the entire function, not just the return.
Here's how the object is set up:
var con = {
b13: function(){
return 12600.535*Math.sqrt((con.b14+459.4)/459.4)
},
b14: function(){
return 20;
}
}
$(document).ready(function(){
console.log(con.b13);
});
This outputs this into the console:
function(){
return 12600.535*Math.sqrt((con.b14+459.4)/459.4)
}
So how do I format this so that it outputs the actual number in the equation?
You need to make b13 and b14 properties with a getter function:
var con = {};
Object.defineProperty(con, "b13", {
get: function() {
return 12600.535*Math.sqrt((con.b14+459.4)/459.4);
}
});
Object.defineProperty(con, "b14", {
get: function() { return 20; }
});
This will cause con.b13 and con.b14 to call the given functions, returning whatever the functions return.
Try console.log(con.b13()); . You are logging the function definition not executing it.
you don't define the properties as functions...
var con = {
b13: 239487,
b12: 923748
};
edit: if some properties need to be functions you have to call them e.g. con.b14(), not con.b14 as a property
You can simply use es5 getters/setters.
var con = {
get b13() {
return 12600.535*Math.sqrt((con.b14+459.4)/459.4);
},
get b14() {
return 20;
}
};
The problem is that your object's properties are functions, but you are trying to call them as if they were values.
For example, if you wanted correctly log con.b13's value to the console, you would need to change the command to:
console.log(con.b13());
What this does is get what con.b13 returns rather than what it is.
If you don't want to go through the hassle of adding a () next to every reference, you can modify the object and define getters like this:
var con = {
get b13() {
return 12600.535 * Math.sqrt((con.b14 + 459.4) / 459.4)
},
get b14() {
return 20;
}
}
If you define the object like this, your original command console.log(con.b13) will work as intended.
I am working on a little project and one of the objects for the project can include update functions being added to an array that is a property of the object.
Example,
/*
Add an update function to the layer
#param function {update} The update to add
*/
Layer.prototype.addUpdate = function (update) {
// Add the update
this.updates.push(update);
};
/*
Remove an update from the layer
#param function {update} The update to remove
*/
Layer.prototype.removeUpdate = function (update) {
this.updates.forEach(function (element, index) {
if (element.toString() === update.toString()) {
this.updates.splice(index, 1);
}
}, this);
};
With the code above I can use it like so;
var layer = new Layer();
var func = function () {
x = 10;
};
layer.addUpdate(func);
layer.removeUpdate(func);
After reading on the internet about doing it this way to compare the functions equality, everywhere I have read says that it is really bad to do so.
Is using toString() on a function really that bad?
Are there any other ways I can do this while only supplying the function for both parameters when adding and removing an update?
UDPATE
Is there a way to check if 2 variables point to the same reference? Example (pseudo);
var a = 10;
var b = a;
var c = a;
if (b and c point to a) //
Sure. Compare the functions themselves:
if(element === update) {
// ...
However, you might have a problem modifying the array while forEach is looping over it.
Hi guys I am writing some code using the object literal pattern, I have function that returns a value:
'currentLocation': function() {
var cL = 0;
return cL;
},
I then need to update the variable 'cL' from another function like this:
teamStatus.currentLocation() = teamStatus.currentLocation() + teamStatus.scrollDistance();
This part is part of another function - however I get an error back stating: invalid assignment left-hand side
I am guessing I can not update the variable in this way, could anyone suggest a better method or point me in the right direction.
Any help would be greatly appreciated.
Going to add more code to highlight what I am trying to do:
'currentLocation': function() {
var cL = 0;
return cL;
},
'increaseTable': function() {
if (teamStatus.currentLocation() <= teamStatus.teamStatusTableHeight() ) {
teamStatus.currentLocation = teamStatus.currentLocation() + teamStatus.scrollDistance();
$("#tableTrackActual").animate({scrollTop: (teamStatus.currentLocation)});
$("#tableMembers").animate({scrollTop: (teamStatus.currentLocation) });
//console.log(teamStatus.currentLocation());
teamStatus.buttonRevealer();
}
}
As you can see increaseTable should update the value of currentLocation - help this sheds more light on what I am trying to achieve.
You're writing teamStatus.currentLocation() =, which calls the function teamStatus.currentLocation and tries to assign to the return value. That isn't valid. You want just teamStatus.currentLocation = — no function call.
The variable inside your function is completely private to that function (and any functions defined within it). If you need to create a number of functions that share a set of private variables, you can do that with a closure. For instance:
var Thing = (function() {
var thingWideData;
function getData() {
return thingWideData;
}
function setData(newData) {
thingWideData = newData;
}
return {
getData: getData,
setData: setData
};
})();
What that does is create a Thing object which has getData and setData functions available for it, which get and set the completely private thingWideData variable contained by the anonymous closure. More about this pattern here and here, although the latter of those is more about private methods than private data.
What your code produces is:
0 = 0 + <some number>
Which variable do you want to update? cL? You are declaring it in the function, you cannot assign a value to it from outside. Depending on the rest of your code, you might be better off with getters and setters:
var object = {
_cL = 0,
get currentLocation() {
return this._cL;
},
set currentLocation(value) {
this._cL = value;
}
}
then you can do:
teamStatus.currentLocation = teamStatus.currentLocation + teamStatus.scrollDistance();
Update:
Regarding IE: If currentLocation should actually be just a number, it might be sufficient to just declare it as property:
var obj = {
currentLocation: 0
}