【问题标题】:Why value of `X` in iife chage based on the way we access it?为什么 iife chage 中“X”的值取决于我们访问它的方式?
【发布时间】:2018-12-11 14:54:30
【问题描述】:

我有以下 js 代码。

var a = (function(){
    var x = 0;
    var y = function(){
        x++;
        console.log(x);
    }
    var z = function(){
        return x;
    }
    return {
        x, y, z
    }
})();

在这里,当我第一次尝试访问 a.x 时,它给了我输出 0(预期 x 初始化为 0),然后我使用函数 @ 递增 x 的值987654325@。但是在将x 的值增加两次(或者可能超过2)之后,当我尝试访问x 的值时,它仍然给了我a.x=0。我无法理解为什么会这样,因为我已经使用函数 y 更改了 x 的值。那为什么它没有改变。

(但是当我通过某个函数访问 x 的值时,它会给出递增的值。为什么会有这种不同的行为。如果我直接访问同一个变量,那么它将给出一些输出,当我返回相同的变量值时它赋予了一些其他价值。为什么?)

var a = (function(){
  var x = 0;
  var y = function(){
	x++;
	console.log(x);
  }
  var z = function(){
	return x;
  }
  return {
	x, y, z
  }
})();

console.log(a.x);
a.y();
a.y();
console.log(a.x);
console.log(a.z());

是因为关闭但不确定。

【问题讨论】:

  • 因为 a.x 只会是它最初设置的值。它不是对变量的引用。
  • 但我正在使用y 更改它的值,那么它应该会更改,但为什么不更改?
  • y 是一个函数……你不是在改变一个函数,而是在执行它。如果变量在我们引用它们之后发生了变化,我们的应用程序就会出现大问题。
  • 谢谢,得到答案。

标签: javascript iife


【解决方案1】:

最后一行:

   return { x, y, z };

等同于:

  return { x: x, y: y, z: z };

所以它将局部变量复制到对象中。对于通过引用复制它们无关紧要的函数或对象,但基元是按值复制的,因此您有两个不同的z,一个局部变量和对象属性。

【讨论】:

  • 谢谢,明白原因了。
【解决方案2】:

当你创建一个对象并返回它时:

return {
  x, y, z
}

对象中的x 属性接收本地变量x副本。它没有以任何方式绑定到除此之外的局部变量,因此对闭包中变量的后续更改不会反映在该对象中。

你可以做一个吸气剂:

return {
  get x() { return x; },
  y, z
};

这将导致对返回对象的“x”属性的任何访问获取闭包中x 的当前值。

【讨论】:

  • 谢谢,明白原因了。
  • 我猜“局部变量的副本”的措辞有点令人困惑,因为如果x 是一个对象,那么严格意义上来说,这不是一个副本。更正确的说法是 {x}(通常是 y=x)绑定到 x 的(当前)值,而不是 x 本身。
  • @georg 即使对于一个对象,赋值总是复制源的 real 值;对对象的引用是一个 reference 值,虽然引用的对象可以在内部修改,但引用不会。如果闭包将新对象分配给本地x,换句话说,返回对象中的x 属性仍将引用原始对象。
  • @Pointy:感谢您的解释;)只是说“变量的副本”听起来令人困惑-您不能真正“复制”变量(这只是一个名称)。
  • 哦,我不反对;像 JavaScript 这样的语言中“值”的实际精确语义是复杂而微妙的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
  • 2018-01-07
  • 1970-01-01
  • 1970-01-01
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多