24

単項演算子「++」を使用するためのテスト状況は次のとおりです。

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

この場合、出力は次のようになります。

0
0

++ 演算子の位置はオペランドの後ろにあるため、その優先順位は割り当ての優先順位よりも低いため、"j" は最初にそれ自体の値 (ie0) を受け取り、その後インクリメントされると予想します。では、なぜ 2 番目の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 に割り当てます
    • jRHS がその「記憶された」値(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

Postfix Increment Operator の ECMA 仕様によると、

  1. lhs を LeftHandSideExpression を評価した結果とします。
  2. 次の条件がすべて真の場合、SyntaxError 例外をスローします。
    1. Type(lhs) は Reference が true
    2. IsStrictReference(lhs) は真です
    3. Type(GetBase(lhs)) は環境レコードです
    4. GetReferencedName(lhs) は「eval」または「arguments」のいずれかです
  3. oldValue を ToNumber(GetValue(lhs)) とします。
  4. + 演算子と同じ規則を使用して、値 1 を oldValue に加算した結果を newValue とする (11.6.3 を参照)。
  5. PutValue(lhs, newValue) を呼び出します。
  6. 古い値を返します。

したがって、新しい値が最初にlhs(この場合jは ) に設定され、古い値が式の結果として返され、再び に設定されることは明らかですj。したがって、値は変わりません。

于 2014-01-20T13:41:48.860 に答える
0

j = j++は、RHS 値を最初に LHS に割り当て、次に RHS を 1 インクリメントすることを意味します。一方、j = ++jRHS を 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 に答える