乐趣区

关于javascript:前端基础知识连续赋值

先看上面这个问题:

var a = {n: 1};
var b = a;
a.x = a = {n: 2};

console.log(a.x); // --> ?
console.log(b.x); // --> ?

要解决这个问题,须要了解:

  • JS 引擎对赋值表达式的解决
  • 赋值运算的右联合性

赋值表达式

形如

A = B

的表达式称为赋值表达式,其中 A 和 B 又别离能够是表达式。B 能够是任意表达式,然而 A 必须是一个 左值

左值:能够被赋值的表达式,在 ES 标准中是用外部类型 援用 (Reference) 形容的。

JS 引擎会按如下步骤解决赋值表达式:

  1. 计算表达式 A,失去一个援用ArRf
  2. 计算表达式 B,失去一个援用BRef
  3. 通过GetValue(BRef),失去一个值BValue
  4. 解析 ARef,如满足肯定条件(不是左值的条件),会报SyntaxError 异样
  5. 通过 PutValue(ARef, BValue) 进行赋值
  6. 返回BValue

赋值运算的右联合性

赋值表达式是右联合的。即:

Exp1 = Exp2 = Exp3 = Exp4

等价于

Exp1 = (Exp2 = (Exp3 = Exp4))

连等赋值解析

依据下面两局部的常识,连等赋值的解析如下:

=> Exp1 = (Exp2 = (Exp3 = Exp4))
=> Ref1 = (Ref2 = (Ref3 = Ref4)) 
=> Ref1 = (Ref2 = (Ref3 = GetValue(Ref4))) 
=> Ref1 = (Ref2 = (Ref3 = Value4)) 
=> Ref1 = (Ref2 = Value4) 
=> Ref1 = Value4 
=> Value4

总结一下就是:先从左到右解析各个援用,而后计算最右侧的表达式的值,最初把值从右到左赋给各个援用。

当初回到结尾的问题,前两个 var 语句执行完后,ab 都指向同一个对象{n: 1},对于

a.x = a = {n: 2};

先从左到右先解析各个援用,因而 a.x 中的 a 指向的是对象 {n: 1}b 和此时的 a 指向的是同一个对象

接着 a 被从新赋值为 {n: 2},再而后a.x 被赋值{n: 2},于是失去

console.log(a.x)  //  undefined
console.log(b.x)  //  {n: 2}

参考

由 ES 标准学 JavaScript(二):深刻了解“连等赋值”问题

12.3 Left-Hand-Side Expressions

11.13.1 Simple Assignment (=)

退出移动版