【问题标题】:Chaining compound assignment operators in JavaScript在 JavaScript 中链接复合赋值运算符
【发布时间】:2012-10-17 21:20:53
【问题描述】:

在 C# 中,

string s = "abc";
s += (s += s);
Console.WriteLine(s);

abcabcabc (http://ideone.com/pFNFX2)。这很好,因为 C# 规范在第 7.16.2 节中明确指出

运算被计算为 x = x op y,除了 x 只计算一次。

但是,在阅读 ECMAScript 5.1 语言规范第 11.3.2 节中对复合赋值运算符的描述时,我在该运算符的语义中看不到这样的“仅一次”限定符。相反,我看到的是:

  1. 设 lref 为计算 LeftHandSideExpression 的结果。
  2. 令 lval 为 GetValue(lref)。
  3. 设 rref 为评估 AssignmentExpression 的结果。
  4. 令 rval 为 GetValue(rref)。
  5. 令 r 为将运算符 @ 应用于 lval 和 rval 的结果。
  6. 如果以下条件都为真,则抛出 SyntaxError 异常:(截断)
  7. 调用 PutValue(lref, r)。
  8. 返回 r.

因此,看起来(对我来说,无论如何)以下 JavaScript 代码

var s = "abc";
s += (s += s);
alert(s);

会提醒abcabcabcabc(因为括号表达式中第 7 行的 PutValue),但无论如何在 Chrome 22 中,它都会提醒 abcabcabc

所以我的问题是:我是误读了规范,还是 Chrome(也许是 V8?)做​​自己的事情不符合规范?

【问题讨论】:

  • 您是否在任何其他浏览器中测试过这种行为是否相同?
  • 如果你分解s += (s += s); 的实际含义,它会变成s = s + (s + s);,我认为这很简单,结果应该是“abcabcabc”
  • 为什么会这样重写?为什么我们不先重写并完全评估右手边......哦...... duh!我想你有答案。

标签: javascript ecmascript-5 side-effects compound-assignment


【解决方案1】:

所以我认为如果你打开操作,你有:

s += (s += s);

s = s + (s += s);
s = s + (s = s + s);    // Can't actually have the "s = " part, it's really just "s + s"
s = s + (s + s);
s = s + s + s;

这意味着结果应该是“abcabcabc”。

【讨论】:

  • 就是这样。关键是语义中的第 2 行。在我们查看右侧之前,它会将 s 评估为 lval。你已经很好地反映在你的崩溃中。
猜你喜欢
  • 2011-11-16
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
相关资源
最近更新 更多