Странное поведение в 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 с нечетными переменными.