2030 votes

Pourquoi utiliser "pour..." avec la matrice d'itération une mauvaise idée?

J'ai été dit de ne pas utiliser "pour..." avec des tableaux en JavaScript. Pourquoi pas?

1699voto

Triptych Points 70247

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'.
}

421voto

CMS Points 315406

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

127voto

Christoph Points 64389

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 en DontEnum; 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és Array.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ême

  • for..in n'est pas garanti pour préserver l'élément de commande

  • c'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

61voto

Pim Jager Points 20018

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

41voto

JacquesB Points 19878

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.

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