0

ネストされた for ループ内で作業していてsplice、理解できない動作に遭遇しました。

var a = [0, 1, 2, 3, 4];

for (b in a) {
    console.log(a);
    for (c in a) {
        console.log(c + '==' + a[c]);
        if (c === "1")
            a.splice(c, 1);
      }
 }

console.log(a);

その出力は奇妙です

    [0, 1, 2, 3, 4]
    "0==0"
    "1==1"
    "2==3"  // why is index 2 referring to value 3 , whereas it should refer to 2
    "3==4"
    [0, 2, 3, 4]
    "0==0"
    "1==2"
    "2==4"  //  index 2 referring to value 4 , whereas it should refer to 3
    [0, 3, 4]
    "0==0"
    "1==3"
    [0, 4]

インデックス 1 をスプライシングしていますが、次の要素をスキップしています。

なぜこの動作...

ここでチェックアウト: http://jsbin.com/isahoj/3/edit

編集:
わかりました、 splicing 後にインデックスをシフトすることは理解していますが、 console.log() を実行した後に splice を呼び出しています...では、以前にどのように接合されていますか?

4

3 に答える 3

5

インデックス 2 が値 3 を参照しているのに、2 を参照する必要があるのはなぜですか

前の繰り返しで、次の方法でエントリを削除したためですsplice

if (c==="1")
    a.splice(c, 1);

...だから、すべてが上にシフトしました(それがspliceそうです)。次に、次のループは でcあり"2"、インデックス 2 のエントリ (現在) は です3


あなたのコメントについて:

わかりました、 splicing 後にインデックスをシフトすることは理解していますが、 console.log() を実行した後に splice を呼び出しています...では、以前にどのように接合されていますか?

さて、戻りましょう:

  1. 内側のループが始まる前は、a次のようになります。

    [0, 1, 2, 3, 4]
    
  2. 内側のループの最初のパスでc"0"、 であり、インデックスのエントリ00であるため、ログ ステートメントは を示します"0==0"spliceは呼び出されておらaず、変更されていないため、次のようになります。

    [0, 1, 2, 3, 4]
    
  3. 内側のループの次のパスでc"1"であり、インデックスのエントリ11であるため、ログ ステートメントは を示します"1==1"。次にsplice 呼び出され、a次のように変更されます。

    [0, 2, 3, 4]
    
  4. 内側のループの次のパスでc"2"、 であり、インデックスのエントリ23(変更され2たため、ではありませんa) であるため、ログ ステートメントは を示します"2==3"

その後、外側のループが再び実行されると、ある時点でc再び"1"あるため、別のエントリが削除され、同じ効果が見られます。

あなたがすべきことは、実際にコードがライブで実行されるのを見て、デバッガーでシングルステップを実行しa、リアルタイムでどのように変化するかを観察することです。console.log最近のすべてのブラウザには、有能なデバッガが組み込まれています。コードにステートメントを散らかす必要はありません。実際に何が起こるかを見ることができます。


それはあなたの問題の理由でfor-inはありませんが、配列インデックスをループするためではなく、オブジェクトのプロパティ名を列挙するためであることに注意してください(これがc==="1"比較が機能する理由であり、プロパティ名は常に文字列です)。詳細:神話と現実for..in

于 2013-02-16T14:32:18.007 に答える
2

要素 1 を削除すると、「a」は次のようになります。

[0, 2, 3, 4]

新しい要素 1 は 2 です。ループの次の繰り返しでは、"c" は 2 であり、a[2]実際には 3 です。

于 2013-02-16T14:32:40.153 に答える
0

-enumerations を使用して配列をループしないfor…inでください。

とはいえ、問題は、.spliceメソッドが配列を変更し、アイテムを削除して、その後にインデックスを調整することです。それでも、反復変数を調整しないため、インデックスをスキップします-古いインデックス「1」はすでにアクセスされており、次は新しい「1」ではなく「2」になります。

これを解決するには、逆方向にループするか、反復カウンターを数または削除されたアイテムだけ減らします。ただし、インデックスに再度アクセスすると、条件は常に満たされ、2 番目の要素がなくなるまで配列からすべての 2 番目の要素を連続して削除します。これが目標かどうかはわかりません。

于 2013-02-16T14:35:32.417 に答える