280 votes

Que signifie l'erreur JSLint 'body of a for in' dans une instruction if?

J’ai utilisé JSLint un fichier JavaScript de la mine. Il jeta l’erreur :

Problème au caractère de la ligne 41 9 : le corps d’un car dans doivent être encapsulées dans un if instruction pour filtrer les propriétés indésirables du prototype.

Que cela signifie-t-il ?

468voto

vava Points 11364

Tout d'abord, ne jamais utiliser un for in boucle pour énumérer sur un tableau. Jamais. Utiliser les bonnes vieilles for(var i = 0; i<arr.length; i++).

La raison derrière cela est le suivant: chaque objet en JavaScript a un champ spécial appelé prototype. Tout ce que vous ajoutez à ce champ va être accessible sur tous les objets de ce type. Supposons que vous voulez tous les tableaux d'avoir un cool nouvelle fonction appelée filter_0 filtre les zéros.

Array.prototype.filter_0 = function() {
    var res = [];
    for (var i = 0; i < this.length; i++) {
        if (this[i] != 0) {
            res.push(this[i]);
        }
    }
    return res;
};

console.log([0, 5, 0, 3, 0, 1, 0].filter_0());
//prints [5,3,1]

C'est un moyen d'étendre les objets et ajouter de nouvelles méthodes. Beaucoup de bibliothèques de le faire. Cependant, regardons comment for in travaille maintenant:

var listeners = ["a", "b", "c"];
for (o in listeners) {
    console.log(o);
}
//prints:
//  0
//  1
//  2
//  filter_0

Voyez-vous? Soudain, elle pense filter_0 est un autre indice de tableau. Bien sûr, il n'est pas vraiment un indice numérique, mais for in énumère les champs objet, pas seulement des indices numériques. Nous sommes donc maintenant énumération dans tous les index numérique et filter_0. Mais filter_0 n'est pas un champ d'un tableau d'objets, chaque objet array a cette propriété.

Heureusement, tous les objets ont un hasOwnProperty méthode, qui vérifie si ce champ appartient vraiment à l'objet lui-même ou si elle est simplement hérité de la chaîne de prototype et appartient donc à tous les objets de ce type.

for (o in listeners) {
    if (listeners.hasOwnProperty(o)) {
       console.log(o);
    }
}
 //prints:
 //  0
 //  1
 //  2

Note que, même si ce code fonctionne comme prévu pour les tableaux, vous ne devriez jamais, jamais, utilisez for in et for each in pour les tableaux. Rappelez-vous que for in énumère les champs d'un objet, pas de tableau d'index ou de valeurs.

var listeners = ["a", "b", "c"];
listeners.happy = "Happy debugging";

for (o in listeners) {
    if (listeners.hasOwnProperty(o)) {
       console.log(o);
    }
}

 //prints:
 //  0
 //  1
 //  2
 //  happy

93voto

Breton Points 9625

Douglas Crockford, l'auteur de jslint a (écrit et parlé) à propos de cette question de nombreuses fois. Il y a une section sur cette page de son site web qui couvre ce:

pour la Déclaration

Un pour la classe des déclarations devraient avoir le formulaire suivant:

for (initialization; condition; update) {
    statements
}

for (variable in object) {
    if (filter) {
        statements
    } 
}

Le premier formulaire doit être utilisé avec des tableaux et des boucles d'une predeterminable nombre d'itérations.

Le deuxième formulaire doit être utilisé avec objets. Sachez que les membres qui sont ajoutées sur le prototype de la objet sera inclus dans le l'énumération. Il est sage de programme défensivement à l'aide de la hasOwnProperty méthode pour distinguer les vrais membres de l'objet:

for (variable in object) {
    if (object.hasOwnProperty(variable)) {
        statements
    } 
}

Crockford a également une série de vidéos sur YUI théâtre où il en parle. Crockford de la série de vidéos/discussions à propos de javascript sont un must si vous êtes même un peu de sérieux à propos de javascript.

7voto

wade Points 51

@tous: tout est dans le JavaScript est un objet (), de sorte que des déclarations comme "seulement l'utiliser sur des objets" sont un peu trompeuses. En outre, le JavaScript n'est pas fortement typé, de sorte que 1 == "1" est vrai (bien que 1 === "1" n'est pas, Crockford est grande sur ce sujet). Quand il s'agit de la progromatic concept de tableaux en JS, la saisie est important dans la définition.

@Brenton - Pas besoin d'être une terminologie dictateur; "tableau associatif", "dictionnaire", "hash", "objet", ces concepts de la programmation s'appliquer à une structure en JS. C'est le nom (clé, l'indice de la valeur des paires, où la valeur peut être n'importe quel autre objet (chaînes de caractères sont des objets trop)

Donc, new Array() est le même que []

new Object() est à peu près similaire à l' {}

var myarray = [];

Crée une structure qui est un tableau avec la restriction que tous les index (aka touches) doit être un nombre entier. Il permet également à l'auto attribution de nouveaux indices via .push()

var myarray = ["one","two","three"];

Est en effet préférable de traiter via for(initialization;condition;update){

Mais qu'en est:

var myarray = [];
myarray[100] = "foo";
myarray.push("bar");

Essayez ceci:

var myarray = [], i;
myarray[100] = "foo";
myarray.push("bar");
myarray[150] = "baz";
myarray.push("qux");
alert(myarray.length);
for(i in myarray){
    if(myarray.hasOwnProperty(i)){  
        alert(i+" : "+myarray[i]);
    }
}

Peut-être pas la meilleure utilisation d'un tableau, mais juste une illustration de ce que les choses ne sont pas toujours évident.

Si vous connaissez vos clés, et certainement si elles ne sont pas des nombres entiers, votre seul tableau comme le choix de la structure est l'objet.

var i, myarray= {
   "first":"john",
   "last":"doe",
   100:"foo",
   150:"baz"
};
for(i in myarray){
    if(myarray.hasOwnProperty(i)){  
        alert(i+" : "+myarray[i]);
    }
}

6voto

HRJ Points 4750

Réponse de vava est sur la marque. Si vous utilisez jQuery, puis le `` fonction s’occupe de cela, c’est pourquoi il est plus sûr à utiliser.

3voto

tomfumb Points 37

Sûrement, c'est un peu extrême de dire

...ne jamais utiliser dans la boucle de énumérer sur un tableau. Jamais. Utilisation bon vieux for(var i = 0; j'<arr.longueur; i++)

?

Il convient de signaler l'article de Douglas Crockford extrait

...Le deuxième formulaire doit être utilisé avec les objets...

Si vous avez besoin d'un tableau associatif ( alias de table de hachage / dictionnaire ) où les touches sont nommés à la place de la indexé numériquement, vous aurez à mettre en œuvre la présente comme un objet, par exemple, var myAssocArray = {key1: "value1", key2: "value2"...};.

Dans ce cas - myAssocArray.length viendra null (parce que cet objet n'a pas une "longueur" de la propriété), et votre i < myAssocArray.length vous n'obtiendrez pas très loin. En plus de fournir plus de commodité, je m'attends à des tableaux associatifs pour offrir des avantages en matière de performances dans de nombreuses situations, comme le tableau de clés peut être utile propriétés (c'est à dire un membre d'une pile est la propriété de l'ID ou le nom), ce qui signifie que vous n'avez pas à parcourir un long tableau à plusieurs reprises d'évaluer si les déclarations de trouver l'entrée de ce tableau que vous êtes après.

De toute façon, merci aussi pour l'explication de la JSLint messages d'erreur, je vais utiliser le "isOwnProperty" vérifier maintenant quand interating par le biais de mon myriade de tableaux associatifs!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X