自2014年7月15日起,MDN guide on working with objects的修订版规定:



但是,在下面的代码段中,当评估objLit2.val2时,它不使用最后一个值集,该值应为10100;相反,它使用1000,它是在定义objLit2时声明的值。为什么会这样呢?

var i = 1000;

function iPlus3() {
  alert("iPlus3");

  return i + 3;
}

var objLit2 = {
  val: iPlus3,
  val2: i = i + 1
};

function setValue() {
  i = 10;
  console.log("objLit2Val1", objLit2.val(), objLit2.val2); // Outputs 13 1001 and not 13 11

  i = 100;
  console.log("objLit2Val2", objLit2.val(), objLit2.val2); // Outputs 103 1001 and not 103 101

  // If `val` is interpreted at the time of the call, why is `val2` not also interpreted on each call?
}

setValue();

最佳答案

objLit2是顶级声明。因此,它将在您的脚本首次执行时进行评估。评估后,将设置属性objLit2.val2的值。除非您有意识地更改objLit2.val2属性的值,否则不会因为在代码的其他地方引用objLit2而获得不同的值。

一旦对objLit2进行了评估,属性objLit2.val2就会包含一个不再与变量i关联的原始编号。 objLit2.val2的值是独立存在的,其值不会受到任何其他变量的更改的影响。

javascript中的基元(如数字和 bool 值)存储为与其他任何变量均不相关的不同值。 javascript中的对象存储为对原始对象的引用。由于objLit2.val2是一个数字,因此它只是一个独立的值,独立存在。

因此,您可以执行以下操作:

var i = 1000;
var objLit2 = { val : iPlus3, val2 : i = i + 1 };
console.log(objLit2.val2);    // shows 1001
i += 1000;
console.log(objLit2.val2);    // still shows 1001

另一方面,将对象存储为对原始对象的引用。因此,如果您这样做:
var indexes = [1,2,3];
var objLit2 = { val : indexes, val2 : i = i + 1 };
console.log(objLit2.indexes);    // shows [1,2,3]
indexes[0] = 0;
console.log(objLit2.indexes);    // shows [0,2,3]

因为数组是对象,所以当您在objLit2文字中指定数组时,它只是存储对该数组的引用(而不是数组的单独副本)。如果更改原始数组,则将在包含对该数组引用的所有其他变量中看到该更改。

听起来您引用的内容将适用于在某个范围内(例如在函数内部)声明的对象,因为每次创建该范围时(例如,每次运行该函数)都会重新评估它们。

关于javascript - 为什么每次读取属性时都不会重新评估对象初始化器中的表达式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24836259/

10-13 02:21