Странное поведение в Javascript для... в цикле

Я делаю Javascript игру с тегом canvas, и я использую расширенный цикл для обновления позиций игрока.

Вкратце:

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;
    }
}

За пределами цикла for в позиции 1 я могу получить доступ к правильному значению участников [0].xvel. Внутри цикла for в позиции 2 a.xvel undefined. Может кто-нибудь объяснить мне, что происходит?

Ответ 1

Оператор for...in предназначен для итерации по свойствам объекта, глядя, что ваш код кажется, что actors является массивом (вы устанавливаете начальный элемент с индексом 0).

Этот оператор также будет сканировать цепочку прототипов, если вы расширили Array.prototype, эти свойства будут итерированы, а также порядок итерации не оправдано.

Я бы порекомендовал вам избежать проблем и выполнить итерацию с использованием обычного цикла:

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)) {
    //
  }
}

Ответ 2

похоже, что вы пытаетесь получить доступ к свойствам объекта по имени, а не по значению здесь. индекс в этом случае "0" присваивается "a" в цикле for/in.

то, что вы хотите сделать, - это доступ к значению члена массива, то есть: players [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;
}

Ответ 3

Попробуйте использовать actors[a].xpos вместо a.xpos.

См. здесь дополнительную информацию о JavaScript for-in loops.

Ответ 4

Конструкция for (x in y) выполняет итерацию через индексы массива, а не его членов.

Ответ 5

Другой вариант - использовать библиотеку underscore:

_.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;
});

Одна приятная особенность этого функционального шаблона итерации заключается в том, что вы можете использовать var для объявления переменных в цикле, которые привязаны к телу цикла, что помогает избежать укусов правил JavaScript с нечетными переменными.