gnosis23 / hello-world-blog

还是 issues 里面写文章方便
https://bohao.work
0 stars 0 forks source link

04-赋值操作符的执行过程 #73

Open gnosis23 opened 4 years ago

gnosis23 commented 4 years ago

赋值操作符的执行过程

看了下周爱民老师一篇讲赋值操作符的文章( 03|a.x = a = {n:2} ),尝试自己分析一下。

看一下下面的代码。想想代码的执行过程究竟是什么样的呢?

var a = { n: 2 };
a.x = a = { n: 3 };
console.log(a.x);

第一行就不用解释了... 第二行语句是一个赋值操作,它在标准中的产生式 表达式1 为:

AssignmentExpression ::= LeftHandSideExpression = AssignmentExpression

通过这个产生式,其实我们可以发现,a.x = a = { n: 3 } 其实是由两个部分组成:

Assignment Expression

然后我们来看一下,标准中是如何执行这个表达式1的:

AssignmentExpression : LeftHandSideExpression = AssignmentExpression

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`

提炼一下,主要有以下几步:

有两个问题:

Reference值

如果学过c语言,Reference就是个指针。JavaScript 虽然没有直接获取 Reference 的手段,但某些操作符可以作用于 Reference ,比如:

引用由三部分组成:

PutValue(V, W) 对 reference 的操作:

赋值表达式返回值

返回 rval

回到问题上来

var a = { n: 2 };
a.x = a = { n: 3 };
console.log(a.x);

那么回到最上面的问题

注意下,虽然 a 引用的值改变了,但是 a.x 里面存储的引用还是老的 { n: 2 },这也好理解。

Reference