web-dev-qa-db-fra.com

"var" ou pas de "var" dans la boucle "for-in" JavaScript?

Quelle est la bonne façon d'écrire un for-in boucle en JavaScript? Le navigateur n'émet aucune plainte concernant l'une des deux approches que je montre ici. Tout d'abord, il y a cette approche où la variable d'itération x est explicitement déclarée:

for (var x in set) {
    ...
}

Et alternativement cette approche qui se lit plus naturellement mais qui ne me semble pas correcte:

for (x in set) {
    ...
}
95
futlib

La première version:

for (var x in set) {
    ...
}

déclare une variable locale appelée x. La deuxième version:

for (x in set) {
    ...
}

ne fait pas.

Si x est déjà une variable locale (c'est-à-dire que vous avez un var x; ou var x = ...; quelque part plus tôt dans votre portée actuelle (c'est-à-dire la fonction actuelle)), ils seront équivalents. Si x n'est pas déjà une variable locale, l'utilisation de la seconde déclarera implicitement une variable globale x. Considérez ce code:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

vous pouvez vous attendre à ce que cela alerte hey, there, heli, hey, there, copter, mais depuis le x est le même et il alertera hey, there, there, hey, there, there. Tu ne veux pas ça! Utilisation var x dans vos boucles for.

Pour couronner le tout: si la boucle for est dans la portée globale (c'est-à-dire pas dans une fonction), alors la portée locale (la portée x est déclarée dans si vous utilisez var x) est identique à la portée globale (la portée x est implicitement déclarée dans si vous utilisez x sans var), donc les deux versions seront identiques.

35
Claudiu

Vous devez vraiment déclarer les variables locales avec var, toujours.

Vous ne devez pas non plus utiliser les boucles "for ... in" à moins que vous ne soyez absolument sûr que c'est ce que vous voulez faire. Pour parcourir des tableaux réels (ce qui est assez courant), vous devez toujours utiliser une boucle avec un index numérique:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

L'itération à travers un tableau simple avec "for ... in" peut avoir des conséquences inattendues, car votre boucle peut récupérer des attributs du tableau en plus de ceux indexés numériquement.

edit - ici en 2015, il est également bien d'utiliser .forEach() pour parcourir un tableau:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

La méthode .forEach() est présente sur le prototype Array à partir d'IE9.

20
Pointy

En fait, si vous n'aimez pas la déclaration dans l'en-tête for, vous pouvez faire:

var x;
for (x in set) {
    ...
}

Comme mentionné dans d'autres réponses à cette question, ne pas utiliser du tout var produit des effets secondaires inutiles comme l'attribution d'une propriété globale.

11
user422039

Utilisez celui où vous déclarez la variable de boucle avec var. Les variables déclarées implicitement ont une portée différente qui n'est probablement pas celle que vous vouliez.

9
Joel Coehoorn
for(var i = 0; ...)

est un schéma commun mais différent de

for(int i; ...)

en C++ en ce que la variable n'est pas étendue au bloc for. En fait, le var est hissé en haut de la portée (fonction) englobante de sorte qu'un i local sera effectivement disponible à la fois avant la boucle for (après le début de la portée/fonction actuelle) et ensuite.

En d'autres termes, faire:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

est le même que:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6 a le mot clé let (au lieu de var) pour limiter la portée au bloc for.

Bien sûr, vous DEVRIEZ utiliser des variables locales (celles déclarées avec var ou let ou const (dans ES6)) plutôt que des globales implicites.

for(i=0; ...) ou for(i in ...) échouera si vous utilisez "use strict"; (comme vous devriez) et i n'est pas déclaré.

7
PSkocik

Utiliser var est le moyen le plus propre, mais les deux fonctionnent comme décrit ici: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in

Fondamentalement, en utilisant var, vous vous assurez de créer une nouvelle variable. Sinon, vous pourriez accidentellement utiliser une variable précédemment définie.

5
TJHeuvel

Je pense que var est bon pour des raisons de performances.

Javascript ne parcourra pas la portée globale pour voir si x existe déjà ailleurs.

4
neebz

D'un point de vue général, la première version sera pour un index qui doit vivre dans la portée de la boucle, tandis que l'autre serait n'importe quelle variable dans la portée où le constructeur de la boucle a été invoqué.

Si vous allez utiliser l'index de boucle à l'intérieur pour la boucle et que cela ne sera pas requis par les autres dans les lignes suivantes, mieux vaut déclarer la variable avec "var" pour être sûr que "x" est pour l'index de boucle initialisé avec 0, tandis que l'autre, si une autre variable "x" est disponible dans ce contexte, cela sera écrasé par l'index de la boucle - c'est-à-dire que vous aurez des erreurs logiques -.

3