If *LeftHandSideExpression* is neither an *ObjectLiteral* nor an *ArrayLiteral*, then
a. Let `lref` be the result of evaluating *LeftHandSideExpression*
b. `ReturnIfAbrupt(lref)`
c. If `IsAnonymousFunctionDefinition`(AssignmentExpression) and IsIdentifierRef of *LeftHandSideExpression* are both true, then
i. Let `rval` be the result of performing NamedEvaluation for *AssignmentExpression* with argument `GetReferencedName`(lref)
d. Else,
i. let `rref` be the result of evaluating *AssignmentExpression*
ii. Let `rval` be ? `GetValue`(rref)
e. Perform ? `PutValue`(lref, rval)
f. Return `rval`
赋值操作符的执行过程
看了下周爱民老师一篇讲赋值操作符的文章( 03|a.x = a = {n:2} ),尝试自己分析一下。
看一下下面的代码。想想代码的执行过程究竟是什么样的呢?
第一行就不用解释了... 第二行语句是一个赋值操作,它在标准中的产生式
表达式1
为:AssignmentExpression ::= LeftHandSideExpression = AssignmentExpression
通过这个产生式,其实我们可以发现,
a.x = a = { n: 3 }
其实是由两个部分组成:a.x = 右半边
a = { n: 3 }
Assignment Expression
然后我们来看一下,标准中是如何执行这个
表达式1
的:AssignmentExpression : LeftHandSideExpression = AssignmentExpression
提炼一下,主要有以下几步:
lref
rref
, 然后进行 GetValue 操作获取值rval
lref
,rval
)rval
有两个问题:
Reference值
如果学过c语言,Reference就是个
指针
。JavaScript 虽然没有直接获取 Reference 的手段,但某些操作符可以作用于 Reference ,比如:=
rval, 赋值操作符左边是引用引用由三部分组成:
a.b
里面的 aPutValue(V, W) 对 reference 的操作:
赋值表达式返回值
返回 rval
回到问题上来
那么回到最上面的问题
a.x
的 reference,base 为 a (即{n: 2}
)a = { n : 3 }
,返回 { n : 3 },这时候 a 为{ n: 3}
注意下,虽然 a 引用的值改变了,但是 a.x 里面存储的引用还是老的
{ n: 2 }
,这也好理解。Reference