MDN guide on working with objects的修订从 2014 年 7 月 15 日开始,状态:
If an object is created with an object initializer in a top-level script, JavaScript interprets the object each time it evaluates an expression containing the object literal.
但是,在下面的代码片段中,当 objLit2.val2
被评估,它不使用应该是 10
的最后一个值集和 100
;它改为使用 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/