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>
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>
Share
Improve this question
edited Mar 19, 2024 at 13:42
TylerH
21.1k79 gold badges79 silver badges114 bronze badges
asked Jun 26, 2013 at 3:23
klinoreklinore
2,7494 gold badges20 silver badges21 bronze badges
0
4 Answers
Reset to default 4The 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 puter 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 bee more plex. 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./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./ojorax/1/edit
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
once you assign the value of z = 1 + y
z references a different location and there is no further relation between z
and y
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`