Reputation: 2739
After hitting the increment button in my code below, y
is equal to 7, but z
stays equal to 7 instead of changing to 8.
Why don't JavaScript variables update within other variables? Is there a solution to this problem?
<body>
<script>
var y=6;
var z=1+y;
</script>
<button onclick="y++">Increment</button>
<button onclick="alert(y)">What is y?</button>
<button onclick="alert(z)">What is z?</button>
</body>
Upvotes: 3
Views: 1243
Reputation: 71918
The value held on variable z
is calculated the moment you assign it to the variable:
var z=1+y;
If you want it to change, you have to update it manually:
<button onclick="z=++y+1">Increment</button>
Most computer languages behave like that, I believe.
In JavaScript and other languages you can use "getters" and "setters" to achieve what you want, but the code will become more complex. Judge if you really think it's necessary:
<body>
<script>
var vals = {
_y : 0,
z : 0,
set y(val) {
this._y = val;
},
get y() {
this.z = this._y + 1
return this._y;
}
}
vals.y = 6;
vals.z = 1 + vals.y;
</script>
<button onclick="vals.y++">Increment</button>
<button onclick="alert(vals.y)">What is y?</button>
<button onclick="alert(vals.z)">What is z?</button>
</body>
https://jsbin.com/udediy/1/edit
Another, simpler solution is to just use a function. That would work well for the example you gave:
<body>
<script>
var y=6;
var z = function() {
return 1+y;
}
</script>
<button onclick="y++">Increment</button>
<button onclick="alert(y)">What is y?</button>
<button onclick="alert(z())">What is z?</button>
</body>
https://jsbin.com/ojorax/1/edit
Upvotes: 4
Reputation: 39270
y is evaluated when you set z. At that time y is 6 so z is 7. When you increase y then z is not re evaluated (as you've found out).
y=1;
z=++y;//increment y and assign the value to z
// z will be 2;
z=y++;//set z to the value of y and then increment y
// z is now 2 and y is 3
If you want one variable to be dependent on the value of another variable you can't just assgin new values to them. You have to use getters and setters functions:
var myObj={
y:0,
x:0,
setY:function (value){
this.y=value;
this.x=value+1;
},
setX:function (value){
this.x=value;
this.y=value-1;
}
}
myObj.setY(4);
console.log(myObj.x);//=5
myObj.y=2;//breaks setting x, you have to use setters
console.log(myObj.x);//=5
As you can see the line myObj.y=2
breaks setting z so you can't assign values to either myObj.y or myObj.z without breaking it.
To prevent this from happening you have to make x and y private. In JavaScript you can simulate private variables using closures.
A warning for the folling code: if you plan to create multiple instances of your object use constructor functions and have private variables using code conventions (like _privateVar
) instead of real privateness since JS doesn't support it unless you're planning on not using prototype.
var myObj=(function(){
var x=0;// x and y only exist in the funciton body
var y=0;// you cannot access them in myObj.x or .y
return{
setX:function(value){
//maybe check if value is a number here
x=value;
y=value-1;
},
setY:function(value){
//maybe check if value is a number here
y=value;
x=value+1;
},
getX:function(){
return x;
},
getY:function(){
return y;
}
}
})();
myObj.setX(6);
console.log(myObj.getY());//logs 5
myObj.y=22;
console.log(myObj.getY());//still logs 5
Using bfavaretto's syntax with get and set you can assign new values but internally JavaScript will use the getters and setters functions. This does not work in older browsers like IE8 and under.
var myObj={
_y:0,
_x:0,
set y(value){
this._y=value;
this._x=value+1;
},
get y(){
return this._y;
},
set x(value){
this._x=value;
this._y=value-1;
},
get x(){
return this._x
}
}
myObj.x=4;
console.log(myObj.y);//=3
Upvotes: 3
Reputation: 352
One way to do it is to wrap the variable in an object, which is passed by reference rather than by value:
var obj = { y : 6 };
var obj_2 = obj;
alert(obj.y); //6
alert(obj_2.y); // 6
obj.y++;
alert(obj.y); // 7
alert(obj_2.y); // 7`
Upvotes: 1
Reputation: 388316
once you assign the value of z = 1 + y
z references a different location and there is no further relation between z
and y
Upvotes: 1