Tout d'abord, n'utilisez jamais defor in
boucle pour énumérer un tableau. Jamais. Utilisez du bon vieux for(var i = 0; i<arr.length; i++)
.
La raison derrière cela est la suivante: chaque objet en JavaScript a un champ spécial appelé prototype
. Tout ce que vous ajoutez à ce champ sera accessible sur tous les objets de ce type. Supposons que vous vouliez que tous les tableaux aient une nouvelle fonction cool appelée filter_0
qui filtrera 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]
Il s'agit d'une méthode standard pour étendre des objets et ajouter de nouvelles méthodes. De nombreuses bibliothèques le font. Cependant, regardons comment for in
fonctionne maintenant:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
Est-ce que tu vois? Il pense soudainement que filter_0 est un autre index de tableau. Bien sûr, ce n'est pas vraiment un index numérique, mais il for in
énumère les champs d'objet, pas seulement les index numériques. Nous énumérons donc maintenant chaque index numérique et filter_0
. Mais filter_0
n'est pas un champ d'un objet tableau particulier, chaque objet tableau a maintenant cette propriété.
Heureusement, tous les objets ont une hasOwnProperty
méthode qui vérifie si ce champ appartient vraiment à l'objet lui-même ou s'il est simplement hérité de la chaîne 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
Notez que bien que ce code fonctionne comme prévu pour les tableaux, vous ne devez jamais, jamais utiliser for in
et for each in
pour les tableaux. N'oubliez pas for in
qu'énumère les champs d'un objet, pas les index de tableau ou les 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
if (evtListeners.hasOwnProperty(ind))
pour limiter le traitement uniquement aux propriétés propres (non héritées). Pourtant, dans certains cas, vous voulez vraiment parcourir toutes les propriétés, y compris celles héritées. Dans ce cas, JSLint vous oblige à encapsuler le corps de la boucle dans une instruction if pour décider quelles propriétés vous voulez vraiment. Cela fonctionnera et rendra JSlint heureux:if (evtListeners[ind] !== undefined)