【发布时间】: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 节中对复合赋值运算符的描述时,我在该运算符的语义中看不到这样的“仅一次”限定符。相反,我看到的是:
- 设 lref 为计算 LeftHandSideExpression 的结果。
- 令 lval 为 GetValue(lref)。
- 设 rref 为评估 AssignmentExpression 的结果。
- 令 rval 为 GetValue(rref)。
- 令 r 为将运算符 @ 应用于 lval 和 rval 的结果。
- 如果以下条件都为真,则抛出 SyntaxError 异常:(截断)
- 调用 PutValue(lref, r)。
- 返回 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