J'ai vu la question récente où quelqu'un vous a dit cela, mais ils ne visaient que les tableaux. Il est considéré comme une mauvaise pratique pour l'itération à travers des tableaux mais pas nécessairement pour l'itération à travers les membres d'un objet.
mmurch
19
Beaucoup de réponses avec des boucles "for" telles que 'for (var i = 0; i <hColl.length; i ++) {}' par rapport à 'var i = hColl.length; tandis que (i--) {} 'qui, lorsqu'il est possible d'utiliser cette dernière forme, est sensiblement plus rapide. Je sais que c'est tangentiel mais j'ai pensé ajouter ce morceau.
Mark Schultheiss
2
@MarkSchultheiss mais c'est une itération inverse. Existe-t-il une autre version d'itération directe plus rapide?
ma11hew28
5
@Wynand utilise le var i = hCol1.length; for (i;i;i--;) {}cache i car cela fera une différence et simplifiera le test. - plus le navigateur est ancien, plus il y a de différence entre foret whileTOUJOURS mettre en cache le compteur "i" - et bien sûr le négatif ne correspond pas toujours à la situation, et le négatif alors que obfuscate le code un peu pour certaines personnes. et notez var i = 1000; for (i; i; i--) {}et var b =1000 for (b; b--;) {}où je passe de 1000 à 1 et b passe de 999 à 0. - plus le navigateur est ancien, plus le temps tend à favoriser les performances.
Mark Schultheiss
9
Vous pouvez également être intelligent. for(var i = 0, l = myArray.length; i < l; ++i) ...est le plus rapide et le meilleur que vous puissiez obtenir avec l'itération directe.
Mathieu Amiot
Réponses:
1557
La raison en est qu'une construction:
var a =[];// Create a new empty array.
a[5]=5;// Perfectly legal JavaScript that resizes the array.for(var i =0; i < a.length; i++){// Iterate over numeric indexes from 0 to 5, as everyone expects.
console.log(a[i]);}/* Will display:
undefined
undefined
undefined
undefined
undefined
5
*/
Considérez également que les bibliothèques JavaScript peuvent faire des choses comme ça, qui affecteront n'importe quel tableau que 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'.
console.log(x);}/* Will display:
0
1
2
3
4
foo
*/
Historiquement, certains navigateurs ont même itéré sur «longueur», «toString», etc.!
bobince
398
N'oubliez pas d'utiliser (var x in a)plutôt que (x in a)- ne voulez pas créer un global.
Chris Morgan
78
Le premier problème n'est pas une raison pour laquelle il est mauvais, seulement une différence de sémantique. Le deuxième problème me semble être une raison (en plus des conflits entre bibliothèques faisant de même) que la modification du prototype d'un type de données intégré est mauvaise, plutôt que celle de..in est mauvaise.
Stewart
86
@Stewart: Tous les objets dans JS sont associatifs. Un tableau JS est un objet, donc oui, il est aussi associatif, mais ce n'est pas à ça qu'il sert. Si vous souhaitez parcourir l'item d'un objet clés d' , utilisez for (var key in object). Cependant, si vous souhaitez parcourir les éléments d' un tableau , utilisez for(var i = 0; i < array.length; i += 1).
Martijn
42
Vous avez dit pour le premier exemple, qu'il Itère sur des index numériques de 0 à 4, comme tout le monde s'y attend , je m'attends à ce qu'il itère de 0 à 5 ! Puisque si vous ajoutez un élément en position 5, le tableau aura 6 éléments (5 d'entre eux non définis).
stivlo
393
L' for-ininstruction en soi n'est pas une "mauvaise pratique", mais elle peut être mal utilisée , par exemple, pour itérer sur des tableaux ou des objets de type tableau.
Le but de la for-indéclaration est de énumérer les propriétés des objets. Cette déclaration remontera dans la chaîne du prototype, énumérant également les propriétés héritées , une chose qui n'est parfois pas souhaitée.
En outre, l'ordre d'itération n'est pas garanti par la spécification, ce qui signifie que si vous souhaitez "itérer" un objet tableau, avec cette instruction, vous ne pouvez pas être sûr que les propriétés (index de tableau) seront visitées dans l'ordre numérique.
Par exemple, en JScript (IE <= 8), l'ordre d'énumération même sur les objets Array est défini lors de la création des propriété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}
En outre, en parlant des propriétés héritées, si vous, par exemple, étendez la propriété Array.prototype objet (comme certaines bibliothèques comme le font MooTools), ces propriétés seront également énumérées:
Array.prototype.last =function(){returnthis[this.length-1];};for(var p in []){// an empty array// last will be enumerated}
Comme je l'ai déjà dit pour parcourir les tableaux ou les objets de type tableau, la meilleure chose à faire est d'utiliser un boucle séquentielle , telle qu'une boucle plain-old for/ while.
Lorsque vous souhaitez énumérer uniquement les propres propriétés d'un objet (celles qui ne sont pas héritées), vous pouvez utiliser la hasOwnPropertyméthode:
for(var prop in obj){if(obj.hasOwnProperty(prop)){// prop is not inherited}}
Et certaines personnes recommandent même d'appeler directement la méthode Object.prototypepour éviter d'avoir des problèmes si quelqu'un ajoute une propriété nommée hasOwnPropertyà notre objet:
for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj, prop)){// prop is not inherited}}
Question sur le dernier point concernant "hasOwnProperty": Si quelqu'un remplace "hasOwnProperty" sur un objet, vous aurez des problèmes. Mais n'aurez-vous pas les mêmes problèmes si quelqu'un remplace "Object.prototype.hasOwnProperty"? De toute façon, ils vous foutent en l'air et ce n'est pas votre responsabilité, non?
Scott Rippey
Vous dites que ce for..inn'est pas une mauvaise pratique, mais qu'elle peut être utilisée à mauvais escient. Avez-vous un exemple concret de bonnes pratiques, où vous vouliez vraiment parcourir toutes les propriétés d'un objet, y compris les propriétés héritées?
avec cette réponse, j'ai trouvé que peut accéder à la valeur avecfor (var p in array) { array[p]; }
equiman
117
Il y a trois raisons pour lesquelles vous ne devriez pas utiliser for..inpour parcourir les éléments du tableau:
for..infera une boucle sur toutes les propriétés propres et héritées de l'objet tableau qui ne le sont pas DontEnum; cela signifie que si quelqu'un ajoute des propriétés à l'objet de tableau spécifique (il y a des raisons valables - je l'ai fait moi-même) ou modifié Array.prototype(ce qui est considéré comme une mauvaise pratique dans le code qui est censé fonctionner correctement avec d'autres scripts), ces propriétés être réitéré également; les propriétés héritées peuvent être exclues en vérifiant hasOwnProperty(), mais cela ne vous aidera pas avec les propriétés définies dans l'objet tableau lui-même
for..in n'est pas garanti pour préserver l'ordre des éléments
il est lent car vous devez parcourir toutes les propriétés de l'objet tableau et de toute sa chaîne de prototypes et n'obtiendra toujours que le nom de la propriété, c'est-à-dire que pour obtenir la valeur, une recherche supplémentaire sera nécessaire
Parce que for ... in énumère l'objet qui contient le tableau, pas le tableau lui-même. Si j'ajoute une fonction à la chaîne de prototypes de tableaux, elle sera également incluse. C'est à dire
Array.prototype.myOwnFunction =function(){ alert(this);}
a =newArray();
a[0]='foo';
a[1]='bar';for(x in a){
document.write(x +' = '+ a[x]);}
Cela écrira:
0 = foo
1 = bar
myOwnFunction = function () {alert (this); }
Et comme vous ne pouvez jamais être sûr que rien ne sera ajouté à la chaîne de prototype, utilisez simplement une boucle for pour énumérer le tableau:
Les tableaux sont des objets, il n'y a pas "d'objet qui contient le tableau".
RobG
41
Isolément, il n'y a rien de mal à utiliser for-in sur les tableaux. For-in parcourt les noms de propriété d'un objet et, dans le cas d'un tableau "prêt à l'emploi", les propriétés correspondent aux index du tableau. (Les propriétés intégrées telles que length, toStringetc. ne sont pas incluses dans l'itération.)
Cependant, si votre code (ou le framework que vous utilisez) ajoute des propriétés personnalisées aux tableaux ou au prototype de tableau, ces propriétés seront incluses dans l'itération, ce qui n'est probablement pas ce que vous voulez.
Certains frameworks JS, comme Prototype, modifient le prototype Array. D'autres frameworks comme JQuery ne le font pas, donc avec JQuery vous pouvez utiliser en toute sécurité for-in.
Si vous avez un doute, vous ne devriez probablement pas utiliser for-in.
Une autre façon d'itérer à travers un tableau utilise 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 arrcomme:
var arr =["hello"];
arr[100]="goodbye";
Ensuite, le tableau a deux éléments, mais une longueur de 101. L'utilisation de for-in produira deux index, tandis que la boucle for donnera 101 index, où le 99 a une valeur de undefined.
for...ofcompte de 0 à 5 et ignore également Array.prototype.foo. Il montre les valeurs du tableau .
for...inrépertorie uniquement les 5, en ignorant les index de tableau non définis, mais en ajoutant foo. Il affiche les noms des propriétés du tableau .
Réponse plus longue: cela n'en vaut pas la peine, même si l'ordre séquentiel des éléments et des performances optimales ne sont pas nécessaires.
Réponse longue: ça n'en vaut pas la peine ...
L'utilisation for (var property in array)entraînera arrayune itération sur un objet , traversant la chaîne de prototypes d'objet et, finalement, plus lente qu'une forboucle basée sur un index .
for (... in ...) n'est pas garanti de renvoyer les propriétés de l'objet dans un ordre séquentiel, comme on pourrait s'y attendre.
L'utilisation hasOwnProperty()et les !isNaN()vérifications pour filtrer les propriétés de l'objet sont une surcharge supplémentaire qui le rend encore plus lent et annule la raison principale de son utilisation en premier lieu, c'est-à-dire en raison du format plus concis.
Pour ces raisons, il n'existe même pas de compromis acceptable entre performances et commodité. Il n'y a vraiment aucun avantage à moins que l'intention soit de gérer le tableau en tant qu'objet et d'effectuer des opérations sur les propriétés d'objet du tableau.
En plus des raisons données dans d'autres réponses, vous ne voudrez peut-être pas utiliser la structure "for ... in" si vous avez besoin de faire des calculs avec la variable compteur car la boucle parcourt les noms des propriétés de l'objet et donc la variable est une chaîne.
Vous pouvez utiliser le préfixe +au lieu de parseIntsauf si vous avez vraiment besoin d'un entier ou d'ignorer les caractères non valides.
Konrad Borowski
De plus, l'utilisation parseInt()n'est pas recommandée. Essayez parseInt("025");et il va échouer.
Derek 朕 會 功夫
6
@Derek 朕 會 功夫 - vous pouvez certainement utiliser parseInt. Le problème est que si vous n'incluez pas la base, les anciens navigateurs peuvent essayer d'interpréter le nombre (ainsi 025 devient octal). Cela a été corrigé dans ECMAScript 5 mais cela se produit toujours pour les nombres commençant par "0x" (il interprète le nombre comme hex). Pour être sûr, utilisez le radix pour spécifier le nombre comme ça parseInt("025", 10)- qui spécifie la base 10.
La mécanique et l' ordre d'énumération des propriétés ... n'est pas spécifié ...
(Je souligne.)
Cela signifie que si un navigateur le voulait, il pourrait parcourir les propriétés dans l'ordre dans lequel elles ont été insérées. Ou par ordre numérique. Ou dans l'ordre lexical (où "30" précède "4"! Gardez à l'esprit que toutes les clés d'objet - et donc tous les index de tableau - sont en fait des chaînes, ce qui est parfaitement logique). Il pourrait les parcourir par compartiment, s'il implémentait des objets sous forme de tables de hachage. Ou prenez tout cela et ajoutez "à l'envers". Un navigateur peut même itérer de façon aléatoire et être conforme à la norme ECMA-262, tant qu'il visite chaque propriété une seule fois.
En pratique, la plupart des navigateurs aiment actuellement répéter à peu près le même ordre. Mais rien ne dit qu'ils doivent le faire. C'est spécifique à l'implémentation et pourrait changer à tout moment si une autre méthode s'avérait beaucoup plus efficace.
Quoi qu'il en soit, for... ne incomporte aucune connotation d'ordre. Si vous vous souciez de l'ordre, soyez explicite à ce sujet et utilisez une forboucle régulière avec un index.
Comme d'autres l'ont dit, vous pourriez obtenir des clés qui ne sont pas dans votre tableau ou qui sont héritées du prototype. Donc, si, disons, une bibliothèque ajoute une propriété aux prototypes Array ou Object:
Array.prototype.someProperty =true
Vous l'obtiendrez dans le cadre de chaque tableau:
for(var item in [1,2,3]){
console.log(item)// will log 1,2,3 but also "someProperty"}
vous pouvez résoudre ce problème avec la méthode hasOwnProperty:
var ary =[1,2,3];for(var item in ary){if(ary.hasOwnProperty(item)){
console.log(item)// will log only 1,2,3}}
mais cela est vrai pour l'itération sur n'importe quel objet avec une boucle for-in.
Deux
Habituellement, l'ordre des éléments dans un tableau est important, mais la boucle for-in ne sera pas nécessairement itérée dans le bon ordre, c'est parce qu'elle traite le tableau comme un objet, ce qui est la façon dont il est implémenté dans JS, et non comme un tableau. Cela semble être une petite chose, mais cela peut vraiment bousiller les applications et est difficile à déboguer.
Object.keys(a).forEach( function(item) { console.log(item) } )itérer sur un tableau de clés de propriétés propres, pas celles héritées du prototype.
Qwerty
2
Certes, mais comme la boucle for-in, elle ne sera pas nécessairement dans le bon ordre d'index. De plus, cela ne fonctionnera pas sur les anciens navigateurs ne prenant pas en charge ES5.
Dans firefox 3, vous pouvez également utiliser arr.forEach ou for (var [i, v] dans Iterator (arr)) {} mais aucun de ces travaux dans IE, bien que vous puissiez écrire vous-même la méthode forEach.
vava
et pratiquement chaque bibliothèque a sa propre méthode pour cela aussi.
vava
5
Cette réponse est fausse. "longueur" ne sera pas inclus dans l'itération pour-dans. Seules les propriétés que vous ajoutez vous-même sont incluses.
JacquesB
16
Je ne pense pas avoir grand-chose à ajouter, par exemple. Réponse de Triptyque ou réponse de CMS sur les raisons pour lesquelles l'utilisation for...indoit être évitée dans certains cas.
Je voudrais cependant ajouter que dans les navigateurs modernes, il existe une alternative à for...incela qui peut être utilisée dans les cas où elle for...inne peut pas être utilisée. Cette alternative est for...of:
for(var item of items){
console.log(item);}
Remarque :
Malheureusement, aucune version d'Internet Explorer ne prend en charge for...of( Edge 12+ le fait), vous devrez donc attendre un peu plus longtemps pour pouvoir l'utiliser dans votre code de production côté client. Cependant, il doit être sûr de l'utiliser dans votre code JS côté serveur (si vous utilisez Node.js ).
@georgeawg Vous vouliez dire for-of, non for-in, non?
ᆼ ᆺ ᆼ
15
Le problème avec for ... in ...- et cela ne devient un problème que lorsqu'un programmeur ne comprend pas vraiment la langue; ce n'est pas vraiment un bug ou quoi que ce soit - c'est qu'il itère sur tous les membres d'un objet (enfin, tous les membres énumérables , mais c'est un détail pour l'instant). Lorsque vous souhaitez parcourir uniquement les propriétés indexées d'un tableau, le seul moyen garanti de conserver une cohérence sémantique consiste à utiliser un index entier (c'est-à-dire une for (var i = 0; i < array.length; ++i)boucle de style).
Tout objet peut avoir des propriétés arbitraires qui lui sont associées. Il n'y aurait rien de terrible à charger des propriétés supplémentaires sur une instance de tableau, en particulier. Le code qui veut voir uniquement les propriétés de type tableau indexé doit donc s'en tenir à un index entier. Un code qui est pleinement conscient de ce qui for ... infait et a vraiment besoin de voir toutes les propriétés, eh bien, ça va aussi.
Belle explication pointue. Juste curieux. Si j'avais un tableau qui était à l'intérieur d'un objet sous des propriétés de multiplication et que for in, par rapport à une boucle for normale, ces tableaux seraient itérés? (ce qui serait essentiellement une performance lente, non?)
NiCk Newman
2
@NiCkNewman bien l'objet que vous référencez après indans une for ... inboucle sera juste
Pointy
Je vois. Juste curieux parce que j'ai des objets et des tableaux à l'intérieur de mon objet de jeu principal et je me demandais si pour la manche ce serait plus douloureux que simplement une boucle for régulière sur les index.
NiCk Newman
@NiCkNewman bien le thème de toute cette question est que vous ne devriez pas utiliser for ... insur les tableaux; il y a de nombreuses bonnes raisons de ne pas le faire. Ce n'est pas tant un problème de performances qu'un problème de type "assurez-vous qu'il ne casse pas".
Pointy
Eh bien, mes objets sont stockés dans un tableau techniquement, c'est pourquoi j'étais inquiet, quelque chose comme [{a:'hey',b:'hi'},{a:'hey',b:'hi'}]:, mais oui, je comprends.
NiCk Newman
9
De plus, en raison de la sémantique, la façon dont for, inles tableaux sont traités (c'est-à-dire les mêmes que tout autre objet JavaScript) n'est pas alignée avec d'autres langages populaires.
// C#char[] a =newchar[]{'A','B','C'};
foreach (char x in a)System.Console.Write(x);//Output: "ABC"// Javachar[] a ={'A','B','C'};for(char x : a)System.out.print(x);//Output: "ABC"// PHP
$a = array('A','B','C');
foreach ($a as $x) echo $x;//Output: "ABC"// JavaScriptvar a =['A','B','C'];for(var x in a) document.write(x);//Output: "012"
TL&DR: Utiliser la for inboucle dans les tableaux n'est pas mal, en fait bien au contraire.
Je pense que la for inboucle est un joyau de JS si elle est utilisée correctement dans les tableaux. Vous êtes censé avoir un contrôle total sur votre logiciel et savoir ce que vous faites. Voyons les inconvénients mentionnés et réfutons-les un par un.
Il parcourt également les propriétés héritées: Tout d'abord, toutes les extensions de la Array.prototypedoivent avoir été effectuées à l'aide de Object.defineProperty()et leur enumerabledescripteur doit être défini sur false. Toute bibliothèque qui ne le fait pas ne doit pas du tout être utilisée.
Les propriétés que vous ajoutez ultérieurement à la chaîne d'héritage sont comptées: lors de la sous-classification de tableau par Object.setPrototypeOfou par classe extend. Vous devez utiliser à nouveau Object.defineProperty()que par des ensembles par défaut les writable, enumerableet les configurabledescripteurs de propriété à false. Voyons un exemple de sous-classement de tableau ici ...
functionStack(...a){var stack =newArray(...a);Object.setPrototypeOf(stack,Stack.prototype);return stack;}Stack.prototype =Object.create(Array.prototype);// now stack has full access to array methods.Object.defineProperty(Stack.prototype,"constructor",{value:Stack});// now Stack is a proper constructorObject.defineProperty(Stack.prototype,"peak",{value:function(){// add Stack "only" methods to the Stack.prototype.returnthis[this.length-1];}});var s =newStack(1,2,3,4,1);
console.log(s.peak());
s[s.length]=7;
console.log("length:",s.length);
s.push(42);
console.log(JSON.stringify(s));
console.log("length:",s.length);for(var i in s) console.log(s[i]);
Donc, vous voyez ... la for inboucle est maintenant sûre puisque vous vous souciez de votre code.
La for inboucle est lente: Hell no. C'est de loin la méthode d'itération la plus rapide si vous parcourez des tableaux clairsemés qui sont nécessaires de temps en temps. Il s'agit de l'une des astuces de performance les plus importantes à connaître. Voyons un exemple. Nous allons boucler sur un tableau clairsemé.
var a =[];
a[0]="zero";
a[10000000]="ten million";
console.time("for loop on array a:");for(var i=0; i < a.length; i++) a[i]&& console.log(a[i]);
console.timeEnd("for loop on array a:");
console.time("for in loop on array a:");for(var i in a) a[i]&& console.log(a[i]);
console.timeEnd("for in loop on array a:");
@Ravi Shanker Reddy Bonne configuration de l'analyse comparative. Comme je l'ai mentionné dans ma réponse, la for inboucle éclipse les autres "si" le tableau est clairsemé et plus s'il grossit. J'ai donc réorganisé le test de banc pour un tableau clairsemé arr, de taille ~ 10000 avec seulement 50 éléments choisis [42,"test",{t:1},null, void 0]au hasard parmi des indices aléatoires. Vous remarquerez immédiatement la différence. - >> Vérifiez ici << - .
Redu
8
En plus des autres problèmes, la syntaxe "for..in" est probablement plus lente, car l'index est une chaîne, pas un entier.
var a =["a"]for(var i in a)
alert(typeof i)// 'string'for(var i =0; i < a.length; i++)
alert(typeof i)// 'number'
Peu importe probablement beaucoup. Les éléments de tableau sont les propriétés d'un objet basé sur un tableau ou semblable à un tableau, et toutes les propriétés d'objet ont des clés de chaîne. À moins que votre moteur JS ne l'optimise d'une manière ou d'une autre, même si vous utilisiez un nombre, il finirait par être transformé en chaîne pour la recherche.
cHao
Indépendamment de tout problème de performances, si vous êtes nouveau dans JavaScript, utilisez var i in aet attendez-vous à ce que l'index soit un entier, alors faire quelque chose comme a[i+offset] = <value>cela mettra des valeurs complètement aux mauvais endroits. ("1" + 1 == "11").
szmoore
8
Un aspect important est que for...inseulement itère sur les propriétés contenues dans un objet dont l' attribut de propriété énumérable est défini sur true. Donc, si l'on tente de parcourir un objet en utilisantfor...in alors des propriétés arbitraires peuvent être manquées si leur attribut de propriété énumérable est faux. Il est tout à fait possible de modifier l'attribut de propriété énumérable pour les objets Array normaux afin que certains éléments ne soient pas énumérés. Bien qu'en général, les attributs de propriété tendent à s'appliquer aux propriétés de fonction au sein d'un objet.
On peut vérifier la valeur de l'attribut de propriété énumérable d'une propriété en:
myobject.propertyIsEnumerable('myproperty')
Ou pour obtenir les quatre attributs de propriété:
Il s'agit d'une fonctionnalité disponible dans ECMAScript 5 - dans les versions antérieures, il n'était pas possible de modifier la valeur de l'attribut de propriété énumérable (elle était toujours définie sur true).
Le for/ infonctionne avec deux types de variables: les tables de hachage (tableaux associatifs) et le tableau (non associatif).
JavaScript déterminera automatiquement la façon dont son passe à travers les éléments. Donc, si vous savez que votre tableau est vraiment non associatif, vous pouvez utiliser for (var i=0; i<=arrayLen; i++)et ignorer l'itération d'auto-détection.
Mais à mon avis, il vaut mieux utiliser for/ in, le processus requis pour cette détection automatique est très petit.
Une vraie réponse dépendra de la façon dont le navigateur analysera / interprétera le code JavaScript. Il peut changer d'un navigateur à l'autre.
Je ne peux pas penser à d'autres fins pour ne pas utiliser for/ in;
//Non-associativevar arr =['a','b','c'];for(var i in arr)
alert(arr[i]);//Associativevar arr ={
item1 :'a',
item2 :'b',
item3 :'c'};for(var i in arr)
alert(arr[i]);
Pas assez - il est tout à fait correct d'ajouter des propriétés nommées arbitraires aux instances de tableau, et celles-ci seront testées à truepartir des hasOwnProperty()vérifications.
Pointy
Bon point, merci. Je n'ai jamais été assez idiot pour faire ça à un tableau moi-même, donc je n'y ai pas pensé!
JAL
1
@Pointy Je n'ai pas testé cela, mais peut-être que cela peut être surmonté en utilisant une isNaNvérification sur chaque nom de propriété.
WynandB
1
@Wynand idée intéressante; Cependant, je ne vois pas vraiment pourquoi cela en vaut la peine quand itérer avec un simple index numérique est si facile.
Pointy
@WynandB désolé pour la bosse, mais je pense qu'une correction est en ordre: isNaNest pour vérifier si une variable est la valeur spéciale NaN ou non, elle ne peut pas être utilisée pour vérifier des `` choses autres que des nombres '' (vous pouvez aller avec un régulier typeof pour cela).
doldt
6
Ce n'est pas nécessairement mauvais (en fonction de ce que vous faites), mais dans le cas des tableaux, si quelque chose a été ajouté Array.prototype, vous obtiendrez des résultats étranges. Où vous vous attendez à ce que cette boucle s'exécute trois fois:
var arr =['a','b','c'];for(var key in arr){...}
Si une fonction appelée helpfulUtilityMethoda été ajouté à Array« s prototype, votre boucle finirait quatre fois en cours d' exécution: keyserait 0, 1, 2et helpfulUtilityMethod. Si vous ne vous attendiez qu'à des entiers, oups.
Juste une note à propos de SO - il n'y a pas de "ci-dessus" car les commentaires changent constamment l'ordre sur la page. Donc, nous ne savons pas vraiment de quel commentaire vous parlez. Il est bon de dire "dans le commentaire de x personne" pour cette raison.
JAL
@JAL ... ou ajoutez le permalien à la réponse.
WynandB
5
Utiliser la for...inboucle pour un tableau n'est pas faux, bien que je devine pourquoi quelqu'un vous a dit que:
1.) Il existe déjà une fonction ou méthode d'ordre supérieur, qui a cet objectif pour un tableau, mais a plus de fonctionnalités et une syntaxe plus légère, appelée «forEach»: Array.prototype.forEach(function(element, index, array) {} );
2.) Les tableaux ont toujours une longueur, mais for...inet forEachne pas exécuter une fonction pour une valeur qui est'undefined' , seulement pour les indices qui ont une valeur définie. Donc, si vous n'affectez qu'une seule valeur, ces boucles n'exécuteront une fonction qu'une seule fois, mais comme un tableau est énuméré, il aura toujours une longueur jusqu'à l'index le plus élevé qui a une valeur définie, mais cette longueur peut passer inaperçue lors de l'utilisation de ces boucles.
3.) La norme for loop exécutera une fonction autant de fois que vous le définissez dans les paramètres, et comme un tableau est numéroté, il est plus logique de définir combien de fois vous voulez exécuter une fonction. Contrairement aux autres boucles, la boucle for peut alors exécuter une fonction pour chaque index du tableau, que la valeur soit définie ou non.
En substance, vous pouvez utiliser n'importe quelle boucle, mais vous devez vous rappeler exactement comment ils fonctionnent. Comprendre les conditions dans lesquelles les différentes boucles sont réitérées, leurs fonctionnalités distinctes et se rendre compte qu'elles seront plus ou moins appropriées pour différents scénarios.
En outre, il peut être considéré comme une meilleure pratique d'utiliser la forEachméthode que la for...inboucle en général, car elle est plus facile à écrire et a plus de fonctionnalités, vous pouvez donc avoir l'habitude d'utiliser uniquement cette méthode et la norme pour, mais votre appel.
Voir ci-dessous que les deux premières boucles n'exécutent les instructions console.log qu'une seule fois, tandis que la norme for loop exécute la fonction autant de fois que spécifié, dans ce cas, array.length = 6.
var arr =[];
arr[5]='F';for(var index in arr){
console.log(index);
console.log(arr[index]);
console.log(arr)}// 5// 'F'// => (6) [undefined x 5, 6]
arr.forEach(function(element, index, arr){
console.log(index);
console.log(element);
console.log(arr);});// 5// 'F'// => Array (6) [undefined x 5, 6]for(var index =0; index < arr.length; index++){
console.log(index);
console.log(arr[index]);
console.log(arr);};// 0// undefined// => Array (6) [undefined x 5, 6]// 1// undefined// => Array (6) [undefined x 5, 6]// 2// undefined// => Array (6) [undefined x 5, 6]// 3// undefined// => Array (6) [undefined x 5, 6]// 4// undefined// => Array (6) [undefined x 5, 6]// 5// 'F'// => Array (6) [undefined x 5, 6]
Voici les raisons pour lesquelles il s'agit (généralement) d'une mauvaise pratique:
for...inles boucles parcourent toutes leurs propres propriétés énumérables et les propriétés énumérables de leurs prototypes. Habituellement, dans une itération de tableau, nous voulons seulement parcourir le tableau lui-même. Et même si vous-même n'ajoutez rien au tableau, vos bibliothèques ou votre infrastructure peuvent ajouter quelque chose.
Exemple :
Array.prototype.hithere ='hithere';var array =[1,2,3];for(let el in array){// the hithere property will also be iterated over
console.log(el);}
for...inles boucles ne garantissent pas un ordre d'itération spécifique . Bien que l'ordre soit généralement vu dans la plupart des navigateurs modernes de nos jours, il n'y a toujours pas de garantie à 100%.
for...inles boucles ignorent les undefinedéléments du tableau, c'est-à-dire les éléments du tableau qui n'ont pas encore été attribués.
Exemple ::
const arr =[];
arr[3]='foo';// resize the array to 4
arr[4]=undefined;// add another element with value undefined to it// iterate over the array, a for loop does show the undefined elementsfor(let i =0; i < arr.length; i++){
console.log(arr[i]);}
console.log('\n');// for in does ignore the undefined elementsfor(let el in arr){
console.log(arr[el]);}
for ... in est utile lorsque vous travaillez sur un objet en JavaScript, mais pas pour un tableau, mais nous ne pouvons toujours pas dire que c'est une mauvaise façon, mais ce n'est pas recommandé, regardez cet exemple ci-dessous en utilisant for ... in loop:
let txt ="";const person ={fname:"Alireza", lname:"Dezfoolian", age:35};for(const x in person){
txt += person[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35
OK, faisons-le avec Array maintenant:
let txt ="";const person =["Alireza","Dezfoolian",35];for(const x in person){
txt += person[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35
Comme vous voyez le même résultat ...
Mais essayons quelque chose, créons un prototype pour Array ...
Array.prototype.someoneelse ="someoneelse";
Nous créons maintenant un nouveau tableau ();
let txt ="";const arr =newArray();
arr[0]='Alireza';
arr[1]='Dezfoolian';
arr[2]=35;for(x in arr){
txt += arr[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35 someoneelse
Vous voyez quelqu'un d'autre !!! ... Nous faisons en fait une boucle à travers le nouvel objet Array dans ce cas!
C'est donc l'une des raisons pour lesquelles nous devons utiliser for..in soigneusement, mais ce n'est pas toujours le cas ...
Étant donné que les éléments JavaScript sont enregistrés en tant que propriétés d'objet standard, il est déconseillé de parcourir les tableaux JavaScript à l'aide de boucles for ... in car les éléments normaux et toutes les propriétés énumérables seront répertoriés.
bien que cela ne soit pas spécifiquement abordé par cette question, j'ajouterais qu'il y a une très bonne raison de ne jamais l'utiliser pour ... avec un NodeList(comme on l'obtiendrait à partir d'un querySelectorAllappel, car il ne voit pas du tout les éléments retournés, à la place itérer uniquement sur les propriétés NodeList.
var i = hCol1.length; for (i;i;i--;) {}
cache i car cela fera une différence et simplifiera le test. - plus le navigateur est ancien, plus il y a de différence entrefor
etwhile
TOUJOURS mettre en cache le compteur "i" - et bien sûr le négatif ne correspond pas toujours à la situation, et le négatif alors queobfuscate
le code un peu pour certaines personnes. et notezvar i = 1000; for (i; i; i--) {}
etvar b =1000 for (b; b--;) {}
où je passe de 1000 à 1 et b passe de 999 à 0. - plus le navigateur est ancien, plus le temps tend à favoriser les performances.for(var i = 0, l = myArray.length; i < l; ++i) ...
est le plus rapide et le meilleur que vous puissiez obtenir avec l'itération directe.Réponses:
La raison en est qu'une construction:
peut parfois être totalement différent de l'autre:
Considérez également que les bibliothèques JavaScript peuvent faire des choses comme ça, qui affecteront n'importe quel tableau que vous créez:
la source
(var x in a)
plutôt que(x in a)
- ne voulez pas créer un global.for (var key in object)
. Cependant, si vous souhaitez parcourir les éléments d' un tableau , utilisezfor(var i = 0; i < array.length; i += 1)
.L'
for-in
instruction en soi n'est pas une "mauvaise pratique", mais elle peut être mal utilisée , par exemple, pour itérer sur des tableaux ou des objets de type tableau.Le but de la
for-in
déclaration est de énumérer les propriétés des objets. Cette déclaration remontera dans la chaîne du prototype, énumérant également les propriétés héritées , une chose qui n'est parfois pas souhaitée.En outre, l'ordre d'itération n'est pas garanti par la spécification, ce qui signifie que si vous souhaitez "itérer" un objet tableau, avec cette instruction, vous ne pouvez pas être sûr que les propriétés (index de tableau) seront visitées dans l'ordre numérique.
Par exemple, en JScript (IE <= 8), l'ordre d'énumération même sur les objets Array est défini lors de la création des propriétés:
En outre, en parlant des propriétés héritées, si vous, par exemple, étendez la propriété
Array.prototype
objet (comme certaines bibliothèques comme le font MooTools), ces propriétés seront également énumérées:Comme je l'ai déjà dit pour parcourir les tableaux ou les objets de type tableau, la meilleure chose à faire est d'utiliser un boucle séquentielle , telle qu'une boucle plain-old
for
/while
.Lorsque vous souhaitez énumérer uniquement les propres propriétés d'un objet (celles qui ne sont pas héritées), vous pouvez utiliser la
hasOwnProperty
méthode:Et certaines personnes recommandent même d'appeler directement la méthode
Object.prototype
pour éviter d'avoir des problèmes si quelqu'un ajoute une propriété nomméehasOwnProperty
à notre objet:la source
for..in
est beaucoup plus lent que les boucles "normales".for..in
n'est pas une mauvaise pratique, mais qu'elle peut être utilisée à mauvais escient. Avez-vous un exemple concret de bonnes pratiques, où vous vouliez vraiment parcourir toutes les propriétés d'un objet, y compris les propriétés héritées?for (var p in array) { array[p]; }
Il y a trois raisons pour lesquelles vous ne devriez pas utiliser
for..in
pour parcourir les éléments du tableau:for..in
fera une boucle sur toutes les propriétés propres et héritées de l'objet tableau qui ne le sont pasDontEnum
; cela signifie que si quelqu'un ajoute des propriétés à l'objet de tableau spécifique (il y a des raisons valables - je l'ai fait moi-même) ou modifiéArray.prototype
(ce qui est considéré comme une mauvaise pratique dans le code qui est censé fonctionner correctement avec d'autres scripts), ces propriétés être réitéré également; les propriétés héritées peuvent être exclues en vérifianthasOwnProperty()
, mais cela ne vous aidera pas avec les propriétés définies dans l'objet tableau lui-mêmefor..in
n'est pas garanti pour préserver l'ordre des élémentsil est lent car vous devez parcourir toutes les propriétés de l'objet tableau et de toute sa chaîne de prototypes et n'obtiendra toujours que le nom de la propriété, c'est-à-dire que pour obtenir la valeur, une recherche supplémentaire sera nécessaire
la source
Parce que for ... in énumère l'objet qui contient le tableau, pas le tableau lui-même. Si j'ajoute une fonction à la chaîne de prototypes de tableaux, elle sera également incluse. C'est à dire
Cela écrira:
Et comme vous ne pouvez jamais être sûr que rien ne sera ajouté à la chaîne de prototype, utilisez simplement une boucle for pour énumérer le tableau:
Cela écrira:
la source
Isolément, il n'y a rien de mal à utiliser for-in sur les tableaux. For-in parcourt les noms de propriété d'un objet et, dans le cas d'un tableau "prêt à l'emploi", les propriétés correspondent aux index du tableau. (Les propriétés intégrées telles que
length
,toString
etc. ne sont pas incluses dans l'itération.)Cependant, si votre code (ou le framework que vous utilisez) ajoute des propriétés personnalisées aux tableaux ou au prototype de tableau, ces propriétés seront incluses dans l'itération, ce qui n'est probablement pas ce que vous voulez.
Certains frameworks JS, comme Prototype, modifient le prototype Array. D'autres frameworks comme JQuery ne le font pas, donc avec JQuery vous pouvez utiliser en toute sécurité for-in.
Si vous avez un doute, vous ne devriez probablement pas utiliser for-in.
Une autre façon d'itérer à travers un tableau utilise une boucle for:
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:Ensuite, le tableau a deux éléments, mais une longueur de 101. L'utilisation de for-in produira deux index, tandis que la boucle for donnera 101 index, où le 99 a une valeur de
undefined
.la source
À partir de 2016 (ES6), nous pouvons utiliser
for…of
pour l'itération de tableau, comme John Slegers l'a déjà remarqué.Je voudrais juste ajouter ce code de démonstration simple, pour rendre les choses plus claires:
La console affiche:
En d'autres termes:
for...of
compte de 0 à 5 et ignore égalementArray.prototype.foo
. Il montre les valeurs du tableau .for...in
répertorie uniquement les5
, en ignorant les index de tableau non définis, mais en ajoutantfoo
. Il affiche les noms des propriétés du tableau .la source
Réponse courte: ça n'en vaut pas la peine.
Réponse plus longue: cela n'en vaut pas la peine, même si l'ordre séquentiel des éléments et des performances optimales ne sont pas nécessaires.
Réponse longue: ça n'en vaut pas la peine ...
for (var property in array)
entraîneraarray
une itération sur un objet , traversant la chaîne de prototypes d'objet et, finalement, plus lente qu'unefor
boucle basée sur un index .for (... in ...)
n'est pas garanti de renvoyer les propriétés de l'objet dans un ordre séquentiel, comme on pourrait s'y attendre.hasOwnProperty()
et les!isNaN()
vérifications pour filtrer les propriétés de l'objet sont une surcharge supplémentaire qui le rend encore plus lent et annule la raison principale de son utilisation en premier lieu, c'est-à-dire en raison du format plus concis.Pour ces raisons, il n'existe même pas de compromis acceptable entre performances et commodité. Il n'y a vraiment aucun avantage à moins que l'intention soit de gérer le tableau en tant qu'objet et d'effectuer des opérations sur les propriétés d'objet du tableau.
la source
En plus des raisons données dans d'autres réponses, vous ne voudrez peut-être pas utiliser la structure "for ... in" si vous avez besoin de faire des calculs avec la variable compteur car la boucle parcourt les noms des propriétés de l'objet et donc la variable est une chaîne.
Par exemple,
écrirai
tandis que,
écrirai
Bien sûr, cela peut facilement être surmonté en incluant
dans la boucle, mais la première structure est plus directe.
la source
+
au lieu deparseInt
sauf si vous avez vraiment besoin d'un entier ou d'ignorer les caractères non valides.parseInt()
n'est pas recommandée. EssayezparseInt("025");
et il va échouer.parseInt
. Le problème est que si vous n'incluez pas la base, les anciens navigateurs peuvent essayer d'interpréter le nombre (ainsi 025 devient octal). Cela a été corrigé dans ECMAScript 5 mais cela se produit toujours pour les nombres commençant par "0x" (il interprète le nombre comme hex). Pour être sûr, utilisez le radix pour spécifier le nombre comme çaparseInt("025", 10)
- qui spécifie la base 10.Mis à part le fait que
for
...in
boucle sur toutes les propriétés énumérables (ce qui n'est pas la même chose que "tous les éléments du tableau"!), Voir http://www.ecma-international.org/publications/files/ECMA-ST/Ecma -262.pdf , section 12.6.4 (5e édition) ou 13.7.5.15 (7e édition):(Je souligne.)
Cela signifie que si un navigateur le voulait, il pourrait parcourir les propriétés dans l'ordre dans lequel elles ont été insérées. Ou par ordre numérique. Ou dans l'ordre lexical (où "30" précède "4"! Gardez à l'esprit que toutes les clés d'objet - et donc tous les index de tableau - sont en fait des chaînes, ce qui est parfaitement logique). Il pourrait les parcourir par compartiment, s'il implémentait des objets sous forme de tables de hachage. Ou prenez tout cela et ajoutez "à l'envers". Un navigateur peut même itérer de façon aléatoire et être conforme à la norme ECMA-262, tant qu'il visite chaque propriété une seule fois.
En pratique, la plupart des navigateurs aiment actuellement répéter à peu près le même ordre. Mais rien ne dit qu'ils doivent le faire. C'est spécifique à l'implémentation et pourrait changer à tout moment si une autre méthode s'avérait beaucoup plus efficace.
Quoi qu'il en soit,
for
... nein
comporte aucune connotation d'ordre. Si vous vous souciez de l'ordre, soyez explicite à ce sujet et utilisez unefor
boucle régulière avec un index.la source
Principalement deux raisons:
Une
Comme d'autres l'ont dit, vous pourriez obtenir des clés qui ne sont pas dans votre tableau ou qui sont héritées du prototype. Donc, si, disons, une bibliothèque ajoute une propriété aux prototypes Array ou Object:
Vous l'obtiendrez dans le cadre de chaque tableau:
vous pouvez résoudre ce problème avec la méthode hasOwnProperty:
mais cela est vrai pour l'itération sur n'importe quel objet avec une boucle for-in.
Deux
Habituellement, l'ordre des éléments dans un tableau est important, mais la boucle for-in ne sera pas nécessairement itérée dans le bon ordre, c'est parce qu'elle traite le tableau comme un objet, ce qui est la façon dont il est implémenté dans JS, et non comme un tableau. Cela semble être une petite chose, mais cela peut vraiment bousiller les applications et est difficile à déboguer.
la source
Object.keys(a).forEach( function(item) { console.log(item) } )
itérer sur un tableau de clés de propriétés propres, pas celles héritées du prototype.array.forEach
en insérant un certain code dans vos scripts. Voir Polyfill developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Parce qu'il énumère les champs d'objet, pas les index. Vous pouvez obtenir de la valeur avec l'index "longueur" et je doute que vous le vouliez.
la source
Je ne pense pas avoir grand-chose à ajouter, par exemple. Réponse de Triptyque ou réponse de CMS sur les raisons pour lesquelles l'utilisation
for...in
doit être évitée dans certains cas.Je voudrais cependant ajouter que dans les navigateurs modernes, il existe une alternative à
for...in
cela qui peut être utilisée dans les cas où ellefor...in
ne peut pas être utilisée. Cette alternative estfor...of
:Remarque :
Malheureusement, aucune version d'Internet Explorer ne prend en charge
for...of
( Edge 12+ le fait), vous devrez donc attendre un peu plus longtemps pour pouvoir l'utiliser dans votre code de production côté client. Cependant, il doit être sûr de l'utiliser dans votre code JS côté serveur (si vous utilisez Node.js ).la source
for-of
, nonfor-in
, non?Le problème avec
for ... in ...
- et cela ne devient un problème que lorsqu'un programmeur ne comprend pas vraiment la langue; ce n'est pas vraiment un bug ou quoi que ce soit - c'est qu'il itère sur tous les membres d'un objet (enfin, tous les membres énumérables , mais c'est un détail pour l'instant). Lorsque vous souhaitez parcourir uniquement les propriétés indexées d'un tableau, le seul moyen garanti de conserver une cohérence sémantique consiste à utiliser un index entier (c'est-à-dire unefor (var i = 0; i < array.length; ++i)
boucle de style).Tout objet peut avoir des propriétés arbitraires qui lui sont associées. Il n'y aurait rien de terrible à charger des propriétés supplémentaires sur une instance de tableau, en particulier. Le code qui veut voir uniquement les propriétés de type tableau indexé doit donc s'en tenir à un index entier. Un code qui est pleinement conscient de ce qui
for ... in
fait et a vraiment besoin de voir toutes les propriétés, eh bien, ça va aussi.la source
for in
, par rapport à une boucle for normale, ces tableaux seraient itérés? (ce qui serait essentiellement une performance lente, non?)in
dans unefor ... in
boucle sera justefor ... in
sur les tableaux; il y a de nombreuses bonnes raisons de ne pas le faire. Ce n'est pas tant un problème de performances qu'un problème de type "assurez-vous qu'il ne casse pas".[{a:'hey',b:'hi'},{a:'hey',b:'hi'}]
:, mais oui, je comprends.De plus, en raison de la sémantique, la façon dont
for, in
les tableaux sont traités (c'est-à-dire les mêmes que tout autre objet JavaScript) n'est pas alignée avec d'autres langages populaires.la source
TL&DR: Utiliser la
for in
boucle dans les tableaux n'est pas mal, en fait bien au contraire.Je pense que la
for in
boucle est un joyau de JS si elle est utilisée correctement dans les tableaux. Vous êtes censé avoir un contrôle total sur votre logiciel et savoir ce que vous faites. Voyons les inconvénients mentionnés et réfutons-les un par un.Array.prototype
doivent avoir été effectuées à l'aide deObject.defineProperty()
et leurenumerable
descripteur doit être défini surfalse
. Toute bibliothèque qui ne le fait pas ne doit pas du tout être utilisée.Object.setPrototypeOf
ou par classeextend
. Vous devez utiliser à nouveauObject.defineProperty()
que par des ensembles par défaut leswritable
,enumerable
et lesconfigurable
descripteurs de propriété àfalse
. Voyons un exemple de sous-classement de tableau ici ...Donc, vous voyez ... la
for in
boucle est maintenant sûre puisque vous vous souciez de votre code.for in
boucle est lente: Hell no. C'est de loin la méthode d'itération la plus rapide si vous parcourez des tableaux clairsemés qui sont nécessaires de temps en temps. Il s'agit de l'une des astuces de performance les plus importantes à connaître. Voyons un exemple. Nous allons boucler sur un tableau clairsemé.la source
for in
boucle éclipse les autres "si" le tableau est clairsemé et plus s'il grossit. J'ai donc réorganisé le test de banc pour un tableau clairseméarr
, de taille ~ 10000 avec seulement 50 éléments choisis[42,"test",{t:1},null, void 0]
au hasard parmi des indices aléatoires. Vous remarquerez immédiatement la différence. - >> Vérifiez ici << - .En plus des autres problèmes, la syntaxe "for..in" est probablement plus lente, car l'index est une chaîne, pas un entier.
la source
var i in a
et attendez-vous à ce que l'index soit un entier, alors faire quelque chose commea[i+offset] = <value>
cela mettra des valeurs complètement aux mauvais endroits. ("1" + 1 == "11").Un aspect important est que
for...in
seulement itère sur les propriétés contenues dans un objet dont l' attribut de propriété énumérable est défini sur true. Donc, si l'on tente de parcourir un objet en utilisantfor...in
alors des propriétés arbitraires peuvent être manquées si leur attribut de propriété énumérable est faux. Il est tout à fait possible de modifier l'attribut de propriété énumérable pour les objets Array normaux afin que certains éléments ne soient pas énumérés. Bien qu'en général, les attributs de propriété tendent à s'appliquer aux propriétés de fonction au sein d'un objet.On peut vérifier la valeur de l'attribut de propriété énumérable d'une propriété en:
Ou pour obtenir les quatre attributs de propriété:
Il s'agit d'une fonctionnalité disponible dans ECMAScript 5 - dans les versions antérieures, il n'était pas possible de modifier la valeur de l'attribut de propriété énumérable (elle était toujours définie sur true).
la source
Le
for
/in
fonctionne avec deux types de variables: les tables de hachage (tableaux associatifs) et le tableau (non associatif).JavaScript déterminera automatiquement la façon dont son passe à travers les éléments. Donc, si vous savez que votre tableau est vraiment non associatif, vous pouvez utiliser
for (var i=0; i<=arrayLen; i++)
et ignorer l'itération d'auto-détection.Mais à mon avis, il vaut mieux utiliser
for
/in
, le processus requis pour cette détection automatique est très petit.Une vraie réponse dépendra de la façon dont le navigateur analysera / interprétera le code JavaScript. Il peut changer d'un navigateur à l'autre.
Je ne peux pas penser à d'autres fins pour ne pas utiliser
for
/in
;la source
Array
c'estObject
tropfor ... in
fonctionne avec des objets. La détection automatique n'existe pas.Parce qu'il itérera sur les propriétés appartenant aux objets de la chaîne du prototype si vous ne faites pas attention.
Vous pouvez utiliser
for.. in
, assurez-vous simplement de vérifier chaque propriété avec hasOwnProperty .la source
true
partir deshasOwnProperty()
vérifications.isNaN
vérification sur chaque nom de propriété.isNaN
est pour vérifier si une variable est la valeur spéciale NaN ou non, elle ne peut pas être utilisée pour vérifier des `` choses autres que des nombres '' (vous pouvez aller avec un régulier typeof pour cela).Ce n'est pas nécessairement mauvais (en fonction de ce que vous faites), mais dans le cas des tableaux, si quelque chose a été ajouté
Array.prototype
, vous obtiendrez des résultats étranges. Où vous vous attendez à ce que cette boucle s'exécute trois fois:Si une fonction appelée
helpfulUtilityMethod
a été ajouté àArray
« sprototype
, votre boucle finirait quatre fois en cours d' exécution:key
serait0
,1
,2
ethelpfulUtilityMethod
. Si vous ne vous attendiez qu'à des entiers, oups.la source
Vous devez utiliser
for(var x in y)
uniquement sur les listes de propriétés, pas sur les objets (comme expliqué ci-dessus).la source
Utiliser la
for...in
boucle pour un tableau n'est pas faux, bien que je devine pourquoi quelqu'un vous a dit que:1.) Il existe déjà une fonction ou méthode d'ordre supérieur, qui a cet objectif pour un tableau, mais a plus de fonctionnalités et une syntaxe plus légère, appelée «forEach»:
Array.prototype.forEach(function(element, index, array) {} );
2.) Les tableaux ont toujours une longueur, mais
for...in
etforEach
ne pas exécuter une fonction pour une valeur qui est'undefined'
, seulement pour les indices qui ont une valeur définie. Donc, si vous n'affectez qu'une seule valeur, ces boucles n'exécuteront une fonction qu'une seule fois, mais comme un tableau est énuméré, il aura toujours une longueur jusqu'à l'index le plus élevé qui a une valeur définie, mais cette longueur peut passer inaperçue lors de l'utilisation de ces boucles.3.) La norme for loop exécutera une fonction autant de fois que vous le définissez dans les paramètres, et comme un tableau est numéroté, il est plus logique de définir combien de fois vous voulez exécuter une fonction. Contrairement aux autres boucles, la boucle for peut alors exécuter une fonction pour chaque index du tableau, que la valeur soit définie ou non.
En substance, vous pouvez utiliser n'importe quelle boucle, mais vous devez vous rappeler exactement comment ils fonctionnent. Comprendre les conditions dans lesquelles les différentes boucles sont réitérées, leurs fonctionnalités distinctes et se rendre compte qu'elles seront plus ou moins appropriées pour différents scénarios.
En outre, il peut être considéré comme une meilleure pratique d'utiliser la
forEach
méthode que lafor...in
boucle en général, car elle est plus facile à écrire et a plus de fonctionnalités, vous pouvez donc avoir l'habitude d'utiliser uniquement cette méthode et la norme pour, mais votre appel.Voir ci-dessous que les deux premières boucles n'exécutent les instructions console.log qu'une seule fois, tandis que la norme for loop exécute la fonction autant de fois que spécifié, dans ce cas, array.length = 6.
la source
Voici les raisons pour lesquelles il s'agit (généralement) d'une mauvaise pratique:
for...in
les boucles parcourent toutes leurs propres propriétés énumérables et les propriétés énumérables de leurs prototypes. Habituellement, dans une itération de tableau, nous voulons seulement parcourir le tableau lui-même. Et même si vous-même n'ajoutez rien au tableau, vos bibliothèques ou votre infrastructure peuvent ajouter quelque chose.Exemple :
for...in
les boucles ne garantissent pas un ordre d'itération spécifique . Bien que l'ordre soit généralement vu dans la plupart des navigateurs modernes de nos jours, il n'y a toujours pas de garantie à 100%.for...in
les boucles ignorent lesundefined
éléments du tableau, c'est-à-dire les éléments du tableau qui n'ont pas encore été attribués.Exemple ::
la source
for ... in est utile lorsque vous travaillez sur un objet en JavaScript, mais pas pour un tableau, mais nous ne pouvons toujours pas dire que c'est une mauvaise façon, mais ce n'est pas recommandé, regardez cet exemple ci-dessous en utilisant for ... in loop:
OK, faisons-le avec Array maintenant:
Comme vous voyez le même résultat ...
Mais essayons quelque chose, créons un prototype pour Array ...
Nous créons maintenant un nouveau tableau ();
Vous voyez quelqu'un d'autre !!! ... Nous faisons en fait une boucle à travers le nouvel objet Array dans ce cas!
C'est donc l'une des raisons pour lesquelles nous devons utiliser for..in soigneusement, mais ce n'est pas toujours le cas ...
la source
Une boucle for ... in énumère toujours les clés. Les clés de propriétés des objets sont toujours String, même les propriétés indexées d'un tableau:
la source
Depuis https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections
la source
bien que cela ne soit pas spécifiquement abordé par cette question, j'ajouterais qu'il y a une très bonne raison de ne jamais l'utiliser pour ... avec un
NodeList
(comme on l'obtiendrait à partir d'unquerySelectorAll
appel, car il ne voit pas du tout les éléments retournés, à la place itérer uniquement sur les propriétés NodeList.dans le cas d'un seul résultat, j'ai obtenu:
ce qui explique pourquoi mon
for (node in nodes) node.href = newLink;
échec.la source