为什么当它的值所依赖的变量也发生变化时,我的变量的值却没有变化?

问题描述 投票:0回答:4

点击下面代码中的增量按钮后,

y
等于7,但
z
保持等于7而不是更改为8。

为什么 JavaScript 变量不在其他变量中更新?这个问题有解决办法吗?

<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>
javascript variables increment
4个回答
4
投票

变量

z
上保存的值是在将其分配给变量时计算的:

var z=1+y;

如果你想改变,你必须手动更新:

<button onclick="z=++y+1">Increment</button>

我相信大多数计算机语言都是这样的。


在JavaScript和其他语言中你可以使用“getters”和“setters”来实现你想要的,但代码会变得更加复杂。判断一下你是否真的认为有必要:

<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


另一个更简单的解决方案是仅使用函数。这对于您给出的示例非常有效:

<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


2
投票

y 在您设置 z 时计算。此时 y 是 6,所以 z 是 7。当您增加 y 时,z 不会重新计算(正如您所发现的)。

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

如果您希望一个变量依赖于另一个变量的值,您不能只为它们分配新值。您必须使用 getter 和 setter 函数:

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

正如您所看到的,行

myObj.y=2
中断了设置 z,因此您无法在不中断它的情况下为 myObj.y 或 myObj.z 赋值。

为了防止这种情况发生,你必须将 x 和 y 设为私有。在 JavaScript 中,您可以使用 closures 模拟私有变量。

对以下代码的警告:如果您打算创建对象的多个实例,请使用构造函数并使用代码约定(如

_privateVar
)拥有私有变量,而不是真正的私有性,因为JS不支持它,除非您计划不使用原型。

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

使用 bfavaretto 的 get 和 set 语法,您可以分配新值,但 JavaScript 内部将使用 getters 和 setters 函数。这在 IE8 及以下等较旧的浏览器中不起作用。

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

1
投票

一旦您分配

z = 1 + y
z 的值,就会引用不同的位置,并且
z
y

之间没有进一步的关系

1
投票

一种方法是将变量包装在一个对象中,该对象通过引用而不是值传递:

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`
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.