web-dev-qa-db-fra.com

Comportement étrange en Javascript amélioré pour ... en boucle

Je suis en train de créer un jeu Javascript avec la balise canvas et j'utilise une boucle for améliorée pour mettre à jour les positions des joueurs.

En bref:

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

Juste en dehors de la boucle for en position 1, je peux accéder à la valeur correcte de players [0] .xvel. Dans la boucle for en position 2, a.xvel n'est pas défini. Quelqu'un peut-il m'expliquer ce qui se passe?

31
Spencer

L'instruction for...in est destinée à être utilisée pour itérer sur propriétés de l'objet , en regardant votre code, il semble que actors est un tableau (vous définissez l'élément initial avec index 0).

Cette instruction sera également explorer la chaîne de prototypes, si vous avez étendu le Array.prototype, ces propriétés seront itérées, et l'ordre des itérations n'est pas justifié.

Je vous recommande d’éviter les problèmes et de répéter en utilisant une boucle for normale:

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

Si je me trompe et que actors n'est pas un tableau, je vous recommanderais d'utiliser la méthode hasOwnProperty pour vous assurer que la propriété existe dans l'objet lui-même et non pas quelque part dans la chaîne de prototypes:

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

il semblerait que vous essayiez d'accéder aux propriétés de l'objet par le nom, pas à la valeur ici. l'index, dans ce cas "0", est assigné à "a" dans la boucle for/in. 

ce que vous voulez faire, c'est accéder à la valeur du membre du tableau, à savoir: acteurs [a].

essaye ç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

Essayez d’utiliser actors[a].xpos au lieu de a.xpos.

Voir ici pour plus d'informations sur JavaScript for-in loops .

2
Chris Fulstow

La construction for (x in y) itère à travers les index d'un tableau, pas ses membres.

2
harto

Une autre option consiste à utiliser le underscore library:

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

ou si vous ne voulez pas utiliser le trait de soulignement, mais que vous utilisez quand même JQuery, alors vous pouvez faire:

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

Une caractéristique intéressante de ce modèle d'itération fonctionnel est que vous pouvez utiliser var pour déclarer des variables dans la boucle qui sont étendues au corps de la boucle, ce qui permet d'éviter de se faire piquer par les règles de portée de variable impaires de JavaScript.

0