自2014年7月15日起,MDN guide on working with objects的修订版规定:
但是,在下面的代码段中,当评估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/