当您在以下情况下利用括号表示法中的逗号运算符查看要执行的部分时,操作顺序会更清楚:
var a = {}
var b = {}
try{
// Uncaught TypeError: Cannot set property 'y' of undefined
a
[console.log('x'), 'x']
[console.log('y'), 'y']
= (console.log('right hand side'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // 1
var a = {}
var b = {}
try {
// Uncaught TypeError: Cannot read property 'y' of undefined
a
[console.log('x'), 'x']
[console.log('y'), 'y']
[console.log('z'), 'z']
= (console.log('right hand side'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // undefined
看规格:
生产AssignmentExpression : LeftHandSideExpression = AssignmentExpression
评估如下:
令lref为评估LeftHandSideExpression的结果。
令rref为评估AssignmentExpression的结果。
令rval为GetValue(rref)
。
抛出SyntaxError异常,如果...(无关)
致电PutValue(lref, rval)
。
PutValue
是什么抛出TypeError
:
让O成为ToObject(base)
。
如果[[CanPut]]
使用参数P 调用O 的内部方法的结果为false,则
一个。如果Throw为true,则抛出TypeError异常。
无法将任何内容分配给of的属性undefined
-的[[CanPut]]
内部方法undefined
将始终返回false
。
换句话说:解释器解析左侧,然后解析右侧,如果无法分配左侧的属性,则抛出错误。
当你做
a.x.y = b.e = 1
左侧成功解析,直到PutValue
被调用;直到解析右侧后,才会考虑该.x
属性求值的事实undefined
。解释器将其视为“将一些值分配给undefined的属性y”,并分配给undefined
only throws inside 的属性PutValue
。
相反:
a.x.y.z = b.e = 1
解释器永远不会试图分配给该z
属性,因为它首先必须解析a.x.y
为一个值。如果a.x.y
解析为一个值(甚至为undefined
),也可以- PutValue
像上面一样抛出错误。但是访问 a.x.y
会引发错误,因为y
无法访问属性undefined
。
b.z = 1
并b.e = 1
首先执行(给出右键关联=
),然后a.x.y.z = ...
执行和失败; 为什么b
分配在一种情况下通过而在另一种情况下不通过?