Javascript 评估的增量操作顺序
Javascript increment operation order of evaluation
我知道 postfix/prefix increment/decrement 操作员的工作。而在javascript中,这似乎没有什么不同。
虽然我可以很容易地猜到这一行的结果:
var foo = 10; console.log(foo, ++foo, foo, foo++, foo);
// output: 10 11 11 11 12
as ++
运算符出现在单独的表达式中。
它变得有点复杂,因为这些运算符出现在同一个表达式中:
var foo = 10; console.log(foo, ++foo + foo++, foo);
// output[1]: 10 22 12
// Nothing unexpected assuming LTR evaluation
var foo = 10; console.log(foo, foo++ + ++foo, foo);
// output[2]: 10 22 12
// What? Ordering is now different but we have the same output.
// Maybe value of foo is evaluated lazily...
var foo = 10; console.log(foo, foo + ++foo, foo);
// output[3]: 10 21 11
// What?! So first 'foo' is evaluated before the increment?
我的问题是,Javascript(在本例中为 V8,正如我在 Chrome 中测试的那样)如何以不同方式评估第二个和第三个示例中的加法表达式?
为什么 foo
最终的评估结果与 foo++
不同。后缀 ++
不应该在表达式之后递增并且只在表达式内计算为 foo
吗?
var foo = 10; console.log(foo, ++foo + foo++, foo);
++foo + foo++
11 + 11
预递增将 foo 设置为 11,然后再次将其添加到 foo,它仍然是 11,在 foo 再次递增之前评估为 22。
var foo = 10; console.log(foo, foo++ + ++foo, foo);
foo++ + ++foo
10 + 12
当我们到达 ++foo 时,该值已经与 foo++ 相关
var foo = 10; console.log(foo, foo + ++foo, foo);
foo + ++foo
10 + 11
foo 在我们将它添加到 foo 之前递增,因此给我们 10 + 11
摘要
基本上这完全取决于将它们加在一起时 foo 的当前值。
看看:
foo++ + ++foo
在心里改写为:
foo++ →
addition_lhs = foo // addition_lhs == 10
foo += 1 // foo == 11
++foo →
foo += 1 // foo == 12
addition_rhs = foo // addition_rhs == 12
addition_lhs + addition_rhs == 10 + 12 == 22
和foo + ++foo
:
foo →
addition_lhs = foo // addition_lhs == 10
++foo →
foo += 1 // foo == 11
addition_rhs = foo // addition_rhs == 11
addition_lhs + addition_rhs == 10 + 11 == 21
所以一切都是从左到右计算的,包括递增。
要理解的关键规则是,在 JavaScript 中执行 整个 左侧 (LHS),并在任何操作完成之前记住值右侧 (RHS)。
您可以通过 reading the standard 确认评估顺序,或者只是在表达式中放置一个运行时错误,然后看看会发生什么:
alert(1) + alert(2) + (function () { throw Error(); })() + alert(3)
请理解,当您使用 foo++
时,您是在告诉 "compiler":将其推入堆栈后,将其递增。当您使用 ++foo
时,您是在告诉另一种方式:递增它然后将其推入堆栈。
++
运算符优先于 +
,因为 "compiler" 以这种方式读取表达式 (foo++)+(++foo)
我知道 postfix/prefix increment/decrement 操作员的工作。而在javascript中,这似乎没有什么不同。
虽然我可以很容易地猜到这一行的结果:
var foo = 10; console.log(foo, ++foo, foo, foo++, foo);
// output: 10 11 11 11 12
as ++
运算符出现在单独的表达式中。
它变得有点复杂,因为这些运算符出现在同一个表达式中:
var foo = 10; console.log(foo, ++foo + foo++, foo);
// output[1]: 10 22 12
// Nothing unexpected assuming LTR evaluation
var foo = 10; console.log(foo, foo++ + ++foo, foo);
// output[2]: 10 22 12
// What? Ordering is now different but we have the same output.
// Maybe value of foo is evaluated lazily...
var foo = 10; console.log(foo, foo + ++foo, foo);
// output[3]: 10 21 11
// What?! So first 'foo' is evaluated before the increment?
我的问题是,Javascript(在本例中为 V8,正如我在 Chrome 中测试的那样)如何以不同方式评估第二个和第三个示例中的加法表达式?
为什么 foo
最终的评估结果与 foo++
不同。后缀 ++
不应该在表达式之后递增并且只在表达式内计算为 foo
吗?
var foo = 10; console.log(foo, ++foo + foo++, foo);
++foo + foo++
11 + 11
预递增将 foo 设置为 11,然后再次将其添加到 foo,它仍然是 11,在 foo 再次递增之前评估为 22。
var foo = 10; console.log(foo, foo++ + ++foo, foo);
foo++ + ++foo
10 + 12
当我们到达 ++foo 时,该值已经与 foo++ 相关
var foo = 10; console.log(foo, foo + ++foo, foo);
foo + ++foo
10 + 11
foo 在我们将它添加到 foo 之前递增,因此给我们 10 + 11
摘要
基本上这完全取决于将它们加在一起时 foo 的当前值。
看看:
foo++ + ++foo
在心里改写为:
foo++ →
addition_lhs = foo // addition_lhs == 10
foo += 1 // foo == 11
++foo →
foo += 1 // foo == 12
addition_rhs = foo // addition_rhs == 12
addition_lhs + addition_rhs == 10 + 12 == 22
和foo + ++foo
:
foo →
addition_lhs = foo // addition_lhs == 10
++foo →
foo += 1 // foo == 11
addition_rhs = foo // addition_rhs == 11
addition_lhs + addition_rhs == 10 + 11 == 21
所以一切都是从左到右计算的,包括递增。
要理解的关键规则是,在 JavaScript 中执行 整个 左侧 (LHS),并在任何操作完成之前记住值右侧 (RHS)。
您可以通过 reading the standard 确认评估顺序,或者只是在表达式中放置一个运行时错误,然后看看会发生什么:
alert(1) + alert(2) + (function () { throw Error(); })() + alert(3)
请理解,当您使用 foo++
时,您是在告诉 "compiler":将其推入堆栈后,将其递增。当您使用 ++foo
时,您是在告诉另一种方式:递增它然后将其推入堆栈。
++
运算符优先于 +
,因为 "compiler" 以这种方式读取表达式 (foo++)+(++foo)