24

下面是一个使用一元运算符“++”的测试情况:

var j = 0 ;
console.log(j);
j = j++;
console.log(j);

为此,输出为:

0
0

由于 ++ 运算符的位置在操作数的后面,所以它的优先级低于赋值的优先级,我希望“j”首先接收自身的值(即 0),然后递增。那么为什么第二个console.log(j)调用仍然显示“0”?

为了清楚起见,我知道解决方案是:

// 1)
j++;
// 2)
++j;
// 3)
j += 1;
// 4)
j = ++j;

但我需要知道为什么在这种特定情况下不执行增量步骤,而不是如何解决它!

4

5 回答 5

52

使用后增量时,这是一种不直观(但不是“奇怪”!)的行为。

该声明j = j++这样做:

  1. 评估 LHS
    • 在这种情况下,没有什么特别的事情发生,因为您只是命名了一个变量,但情况可能并非总是如此,例如foo() = j++
  2. 评估 RHS
    • 取(0)的当前值j,记为结果;
    • 递增j(得到 1);
  3. 将 RHS 分配给 LHS
    • 回想一下,RHS 评估为j(0) 的“记忆”值。

结果是无操作。

这里的关键是在最终分配之前评估整个 RHS 并执行后增量。


http://www.ecma-international.org/ecma-262/5.1/#sec-11.3.1
http://www.ecma-international.org/ecma-262/5.1/#sec-11.13.1

于 2014-01-20T13:39:41.210 回答
10

根据后缀增量运算符的 ECMA 规范

  1. 令 lhs 为计算 LeftHandSideExpression 的结果。
  2. 如果以下条件都为真,则抛出 SyntaxError 异常:
    1. 类型(lhs)是参考是真的
    2. IsStrictReference(lhs) 为真
    3. Type(GetBase(lhs)) 是环境记录
    4. GetReferencedName(lhs) 是“eval”或“arguments”
  3. 设 oldValue 为 ToNumber(GetValue(lhs))。
  4. 令 newValue 为将值 1 与 oldValue 相加的结果,使用与 + 运算符相同的规则(参见 11.6.3)。
  5. 调用 PutValue(lhs, newValue)。
  6. 返回旧值。

因此,很明显,新值首先设置在lhs(在这种情况下j)上,旧值作为表达式的结果返回,再次设置回j. 所以,价值不会改变。

于 2014-01-20T13:41:48.860 回答
2

++ 所在的位置让您知道在那一刻您将从中获得什么价值

++j; // increment the value and then give it to me.
j++; // give me the value and then increment it.

所以你说

j = j++;

在递增之前将 j 设置为 j 的值。

于 2014-01-20T19:38:25.530 回答
0

j = j++表示先将 RHS 值赋给 LHS,然后将 RHS 加 1。另一方面,j = ++j表示将 RHS 加 1,然后将其赋给 LHS

于 2014-01-27T03:47:35.830 回答
-3

j++ 表示先赋值,然后递增

++j 表示首先递增,然后赋值

所以,

var j = 0 ;
console.log(j);
j = ++j;
console.log(j);

0
1
于 2014-01-20T13:39:30.817 回答