J'ai été dit de ne pas utiliser "pour..." avec des tableaux en JavaScript. Pourquoi pas?
Réponses
Trop de publicités?La raison en est qu'une construction...
var a = [];
a[5] = 5; // Perfectly legal JavaScript that resizes the array.
for (var i=0; i<a.length; i++) {
// Iterates over numeric indexes from 0 to 5, as everyone expects.
}
peut être parfois totalement différent de l'autre...
var a = [];
a[5] = 5;
for (var x in a) {
// Shows only the explicitly set index of "5", and ignores 0-4
}
Considérons aussi que le JavaScript bibliothèques peuvent faire des choses comme ça, qui va affecter n'importe quel tableau vous créez:
// Somewhere deep in your JavaScript library...
Array.prototype.foo = 1;
// Now you have no idea what the below code will do.
var a = [1,2,3,4,5];
for (var x in a){
// Now foo is a part of EVERY array and
// will show up here as a value of 'x'.
}
L' for-in
instruction en elle-même n'est pas une "mauvaise pratique", mais il peut être mal utilisée, par exemple, pour effectuer une itération d'un tableau ou d'une matrice, comme des objets.
Le but de l' for-in
déclaration est de les énumérer sur les propriétés de l'objet, cette déclaration va monter dans la chaîne de prototype, l'énumération également hérité des propriétés, chose qui , parfois, n'est pas souhaitée.
Aussi, l'ordre d'itération n'est pas garanti par la spec., ce qui signifie que si vous voulez "itérer" un objet de tableau, avec cette déclaration, vous ne pouvez pas être sûr que les propriétés (les indices de tableau) sera visité dans l'ordre numérique.
Par exemple, dans JScript (IE <= 8), l'ordre d'énumération, même sur des objets d'ensemble est définie comme les propriétés ont été créés:
var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';
for (var p in array) {
//... p will be 2, 1 and 0 on IE
}
Aussi, en parlant des propriétés héritées, si vous, par exemple, étendre l' Array.prototype
objet (comme certaines bibliothèques comme MooTools), que les propriétés seront également énumérés:
Array.prototype.last = function () { return this[this.length-1]; };
for (var p in []) { // an empty array
// last will be enumerated
}
Comme je l'ai dit avant pour itérer sur des tableaux ou d'une matrice (comme les objets, la meilleure chose est d'utiliser un séquentielle en boucle, comme un bon vieil for
/while
boucle.
Lorsque vous souhaitez énumérer seulement les propriétés d'un objet (ceux qui ne sont pas héritées), vous pouvez utiliser l' hasOwnProperty
méthode:
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// prop is not inherited
}
}
Et certaines personnes recommandent même de l'appel de la méthode directement à partir de Object.prototype
pour éviter d'avoir des problèmes si quelqu'un ajoute une propriété nommée hasOwnProperty
de notre objet:
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
// prop is not inherited
}
}
Il y a trois raisons pour lesquelles vous ne devriez pas utiliser for..in
d'itérer sur les éléments du tableau:
for..in
boucle sur toutes propres et des propriétés héritées de l'objet array qui ne sont pas enDontEnum
; ce qui signifie que si quelqu'un ajoute des propriétés de la matrice spécifique de l'objet (il y a des raisons valables pour cela - je l'ai fait moi-même) ou modifiésArray.prototype
(ce qui est considéré comme une mauvaise pratique dans le code qui est censé bien fonctionner avec d'autres scripts), ces propriétés seront itéré; propriétés héritées peuvent être exclus par la vérification de l'hasOwnProperty()
, mais qui ne sera pas vous aider avec les propriétés définies dans le tableau de l'objet lui-mêmefor..in
n'est pas garanti pour préserver l'élément de commandec'est lent parce que vous avez à pied de toutes les propriétés de l'objet tableau et l'ensemble de sa chaîne de prototype et sera toujours seulement obtenir le nom de la propriété, c'est à dire pour obtenir la valeur, supplémentaires de recherche sera nécessaire
Parce que...dans énumère l'objet qui contient le tableau, pas le tableau lui-même. Si je ajouter une fonction à la tableaux de chaîne de prototype, qui sera également inclus. I. e.
Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
document.write(x + ' = ' + a[x]);
}
Cela permettra d'écrire:
0 = foo 1 = barre myOwnFunction = function() { alert(this; }
Et puisque vous ne pouvez jamais être sûr que rien ne sera ajouté à la chaîne de prototype suffit d'utiliser une boucle for pour énumérer le tableau:
for(i=0,x=a.length;i<x;i++){
document.write(i + ' = ' + a[i]);
}
Cela permettra d'écrire:
0 = foo 1 = barre
Dans l'isolement, il n'y a rien de mal à utiliser pour-en sur les tableaux. Pour en itère sur les noms de propriété d'un objet, et dans le cas d'un "out-of-the-box" array, les propriétés correspond à l'index de tableau. (Le haut-propertes comme length
, toString
et ainsi de suite ne sont pas inclus dans l'itération.)
Toutefois, si votre code (ou le framework que vous utilisez), d'ajouter des propriétés personnalisées à des tableaux ou à la matrice de prototype, ces propriétés seront inclus dans l'itération, ce qui n'est probablement pas ce que vous voulez.
Certains frameworks JS, comme Prototype modifie le Tableau prototype. D'autres frameworks comme JQuery ne fonctionne pas, donc, avec JQuery, vous pouvez utiliser en toute sécurité pour.
Si vous êtes dans le doute, vous ne devriez pas l'utiliser pour.
Une autre façon d'une itération à travers un tableau à l'aide d'une boucle for:
for (var ix=0;ix<arr.length;ix++) alert(ix);
Cependant, cela a un problème différent. Le problème est qu'un tableau JavaScript peut avoir des "trous". Si vous définissez arr
comme:
var arr = ["hello"];
arr[100] = "goodbye";
Puis le tableau de deux éléments, mais une longueur de 100. À l'aide de pour en donnera deux indices, tandis que la boucle for donnera 101 index, où le 99 a une valeur de undefined
.