Javascript加强的for...in循环中出现奇怪行为

33

我正在使用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未定义。有人能解释一下发生了什么吗?


2
请参见此问题:https://dev59.com/hErSa4cB1Zd3GeqPZMVU#1886259 - pramodc84
3
完全不要使用 for-in 循环来遍历数组。 - Bergi
2015年更新:您需要使用for (var a of actors) - Bergi
5个回答

90

for...in语句用于遍历对象属性,根据您的代码,actors是一个数组(您正在设置带有索引0的初始元素)。

如果您扩展了Array.prototype,此语句还将遍历原型链中的属性,并且迭代顺序不得保证。

我建议您避免问题,使用普通的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)) {
    //
  }
}

4

看起来你正在尝试在名称上访问对象属性,而不是值。在这种情况下,“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;
}

2

2
for (x in y) 结构遍历的是数组的索引,而不是其元素。

0

另一个选择是使用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 奇怪的变量作用域规则所困扰。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接