这是一个包含两个赋值运算符的复合表达式:
var a = {n: 1};
var b = a;
a.x = a = {m: 2};
a; // => {m: 2}
b; // => {n: 1, x: {m: 2}}
棘手的部分是第三行:
a.x = a = {m: 2};
恕我直言,赋值运算符=
是右关联的,因此表达式的嵌套结构是:
a.x = (a = {m: 2});
但是根据ES5 Annex D,ES5 中的评估顺序总是从左到右。
产生式AssignmentExpression : LeftHandSideExpression = AssignmentExpression的评估如下:
- 令lref为评估LeftHandSideExpression的结果。
- 令rref为评估AssignmentExpression的结果。
- 设rval为 GetValue( rref )。
- 如果以下条件都为真,则抛出SyntaxError异常: ....有意省略以节省空间
- 放置值(lref,rval)。
- 返回rval。
所以我对从左到右的评估顺序的理解是:
- 首先评估并为其
a.x
返回参考lref1
计算
a = {m: 2}
得到rref1
,因为它也是一个赋值表达式,我们将再次启动该过程(如递归)2.1。首先评估并为其
a
返回参考lref2
2.2. 评估
{m: 2}
并将对象返回{m: 2}
为rref2
2.3. 让
rval2
=GetValue(rref2)
,rval2
对象也是{m: 2}
2.4.
PutValue(lref2, rval2)
, 所以a
将重新绑定对象{m: 2}
而不是{n: 1}
2.5. return
rval2
,即对象{m: 2}
为rref1
(不是引用类型,而是对象)让
rval1
=GetValue(rref1)
,这也是对象{m: 2}
PutValue(lref1, rval1)
,所以lref1
所指的内存地址就是{m: 2}
。并且b.x
仍然引用此地址并将b
更新。
此过程符合 ES5 Spec 并很好地解释了结果。
我的问题是:
上述评价顺序是真是假?如果是假的,还有其他解释吗?
如何正确理解 ES5 中的参考规范类型?它只是一个指向某个内存地址的中间指针吗?