web-dev-qa-db-ja.com

JavaScriptの奇妙な動作がfor ... inループで強化されました

Canvasタグを使用してJavascriptゲームを作成しています。プレーヤーの位置を更新するために拡張されたforループを使用しています。

簡単に言えば:

var actors = new Array();

var player = new Actor(0, 0, img);

actors[0] = player;

function update_positions() {
    //position 1
    for(var a in actors) {
        //position2
        a.xpos += a.xvel;
        a.ypos += a.yvel;
    }
}

位置1のforループのすぐ外側で、actors [0] .xvelの正しい値にアクセスできます。位置2のforループ内では、a.xvelは未定義です。誰かが何が起こっているのか私に説明できますか?

32
Spencer

for...in ステートメントは、object propertiesを反復するために使用することを意図しており、コードを見るとactorsは配列(初期要素をインデックス0で設定しています)。

このステートメントも クロールアップ プロトタイプチェーンになります。Array.prototypeを拡張した場合、これらのプロパティは反復され、反復の順序も保証されません。

problems を避け、通常のforループを使用して繰り返すことをお勧めします。

for (var i = 0; i < actors.length; i++) {
    actors[i].xpos += actor.xvel;
    actors[i].ypos += actor.yvel;
}

私が間違っていて、actorsが配列ではない場合、hasOwnPropertyメソッドを使用して、プロトタイプのどこかではなく、オブジェクト自体にプロパティが存在することを確認することをお勧めします鎖:

for (var name in object) {
  if (object.hasOwnProperty(name)) {
    //
  }
}
86
CMS

ここでは値ではなく、名前のオブジェクトプロパティにアクセスしようとしているようです。インデックス(この場合は「0」)は、for/inループで「a」に割り当てられます。

あなたがしたいことは、配列のメンバーの値にアクセスすることです、すなわち:actors [a]。

これを試して:

for(var a in actors) { // a=0 the first time around the loop,  
    actor = actors[a]; // same thing as actors[0];
    actor.xpos += actor.xvel;
    actor.ypos += actor.yvel;
}
4
jonnyheadphones

actors[a].xposの代わりにa.xposを使用してみてください。

JavaScript for-inループ の詳細については、こちらを参照してください。

2
Chris Fulstow

for (x in y)構文は、配列のメンバーではなく、配列のインデックスを反復処理します。

2
harto

別のオプションは nderscore ライブラリを使用することです:

_.each( actors, function(a) {
    a.xpos += a.xvel;
    a.ypos += a.yvel;
});

または、アンダースコアを使用したくないが、とにかくJQueryを使用している場合は、次のようにすることができます:

$.each( actors, function(i, a) {
    a.xpos += a.xvel;
    a.ypos += a.yvel;
});

この反復の機能パターンの1つの優れた機能は、varを使用して、ループの本体をスコープとするループ内の変数を宣言できることです。これにより、JavaScriptの奇妙な変数スコープ規則に噛まれることを回避できます。