我是JavaScript的新手,刚刚遇到了这个问题.无法通过谷歌搜索和搜索stackoverflow来解决它.代码段如下:
var a = { n : 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b.x);Run Code Online (Sandbox Code Playgroud)
根据我目前的知识,a.x = a = {n:2};等于:
a = {n : 2};
a.x = a;Run Code Online (Sandbox Code Playgroud)
这最终使得等于{n:2, x:{n:2}}.所以a.x应该等于{n:2},因为b = a,所以b.x = {n:2}.但是我在浏览器中运行的结果是:alert(a.x)是undefined和alert(b.x)是[object object].
有人可以解释原因吗?非常感谢.
这是运算符优先级的问题,而这个问题是有3个运营商这里涉及到:=,=,和..
.具有更高的运算符优先级=,这意味着在分配发生之前a.x进行评估.之后,重新分配mid语句不会影响表达式中的值,因为它已经被评估过了.aaa.x
我们可以使用以下代码观察:
var _a;
var logging = false;
Object.defineProperty(window, 'a', {
get: function () {
if (logging) {
console.log('getting a');
}
return _a;
},
set: function (val) {
if (logging) {
console.log('setting a');
}
_a = val;
}
});
a = { n : 1};
var b = a;
logging = true;
a.x = a = {n: 2};
logging = false;
console.log(a.x);
console.log(b.x);Run Code Online (Sandbox Code Playgroud)
我们在这里看到的是,在我们正在讨论的语句的过程中,它的setter a被访问之前被访问,并且它只被访问一次.这告诉我们之前a.x正在评估. a.x = ....
你出错的地方是那个陈述实际上是这样估算的:
a = {n: 2}
[the value that a referred to before the statement started executing].x = {n : 2};
Run Code Online (Sandbox Code Playgroud)
换句话说,标识符a在语句开始执行之前被"绑定",属性引用将在语句的持续时间内引用该绑定值.
在这种情况下,[the value that a referred to before the statement started executing]相当于b,但它不等于新值a.这就是为什么b.x有价值而a.x不是有价值的原因.
你可以说这个过程是这样的:
var a = { n : 1};
var b = a;
var temp = a;
var newVal = {n: 2};
a = newVal;
temp.x = newVal;
console.log(a.x);
console.log(b.x);Run Code Online (Sandbox Code Playgroud)
这会产生与原始代码相同的结果.
的ECMAScript的规格规定了该过程用于评估AssignmentExpression形式的LeftHandSideExpression = AssignmentExpression.前两个步骤是:
这清楚地表明,在评估右侧之前评估分配的左侧.
在这种情况下 ax 是未定义的,因为
由于第二次赋值 (a = {n:2}),ax 中的引用已更改为新的引用值
使用旧引用读取属性值是未定义的,因为它已更改
要查看差异,请添加新属性,如下所示
ax = ay = {n:2} // 这不会改变a的引用
console.log(a.x);//{n:2}
console.log(a.y);//{n:2}
console.log(b.x);//{n:2}
Run Code Online (Sandbox Code Playgroud)
https://codepen.io/nagasai/pen/JpeENv
来自类似问题的更多详细信息 - How does ax = a = {n: b} work in JavaScript?