javascript - JavaScript 中包含两个赋值运算符的复合表达式的求值过程

标签 javascript assignment-operator ecmascript-5 operator-precedence associativity

这是一个包含两个赋值运算符的复合表达式:

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 中的求值顺序始终是从左到右,根据ES5 Annex D .

根据ES5 Section 11.13.1 ,

The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:

  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let rref be the result of evaluating AssignmentExpression.
  3. Let rval be GetValue(rref).
  4. Throw a SyntaxError exception if the following conditions are all true: ....omitted intentionally to save space
  5. PutValue(lref, rval).
  6. Return rval.

所以我对从左到右的评估顺序的理解是:

  1. 首先评估 a.x 并为其返回一个引用 lref1
  2. 计算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 将重新绑定(bind)对象 {m: 2} 而不是 {n: 1}

    2.5。返回rval2,即对象{m: 2}rref1(不是引用类型,而是对象)

  3. rval1 = GetValue(rref1),这也是对象{m: 2}

  4. PutValue(lref1, rval1),因此lref1引用的内存地址将为{m: 2}。并且b.x仍然引用该地址并且b将被更新。

此过程符合 ES5 规范并很好地解释了结果。

我的问题是:

  1. 上述评估顺序是真是假?如果错误,还有其他解释吗?

  2. 如何正确理解ES5中的引用规范类型?它只是一个引用某个内存地址的中间指针吗?

最佳答案

是的,您对运算符顺序的理解似乎是正确的。

ECMAScript 5 section 8.7说:

A Reference consists of three components, the base value, the referenced name and the Boolean valued strict reference flag. The base value is either undefined, an Object, a Boolean, a String, a Number, or an environment record (10.2.1).

从属性访问创建引用的过程在 11.2.1 中定义。 :

  1. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

因此引用lref1保存 a对象值 (以及引用的名称字符串 "x" ),您最初使用 {n: 1} 创建该字符串。引用并不关心它来自的变量;它只关心创建时提供的基值引用名称

更改 a 所持有的值对引用 lref1 所持有的基值没有任何影响lref1继续保持a的原始值(即 {n: 1} 对象)无论 a 是什么创建 lref1 之后执行.

简而言之,从表达式 a.x 创建的引用与变量 a 不再有任何关系一旦创建引用。相反,引用只知道 a 所保存的值。在创建引用时。

关于javascript - JavaScript 中包含两个赋值运算符的复合表达式的求值过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30716349/

相关文章:

javascript - 如何在 chrome headless+puppeteervaluate() 中使用 xpath?

c++ - 如何保护类(class)成员?

javascript - typescript :在类中扩展集会导致错误(构造函数集需要 'new' )

javascript - boxSize 泄漏到全局范围

javascript - 将参数与字段数据一起传递给 onChange 事件上的函数

javascript - 我想在 v-for 标记中设置一个自定义属性,如下面的代码所示,但是如何在 `computed` 方法中获取此属性?

c++ - 常量类成员、赋值运算符和 QList

C++赋值运算符解析

javascript - 在 json 对象数组上添加唯一生成的标识符

javascript - 模块化JS : How to pass variables and event