web-dev-qa-db-fra.com

Est-ce une mauvaise pratique d'utiliser le même nom de variable dans plusieurs boucles for?

Je ne faisais que peloter du code JavaScript en utilisant JSHint. Dans le code, j'ai deux boucles pour les deux utilisées comme ceci:

for (var i = 0; i < somevalue; i++) { ... }

Ainsi, les deux boucles for utilisent le var i pour l'itération.

Maintenant, JSHint me montre une erreur pour la deuxième boucle for: "'i' est déjà défini". Je ne peux pas dire que ce n'est pas vrai (car c'est évidemment le cas) mais j'ai toujours pensé que cela n'aurait pas d'importance car le var i n'est utilisé qu'à cet endroit spécifique.

Est-ce une mauvaise pratique d'utiliser les boucles for de cette façon? Dois-je utiliser une variable différente pour chaque boucle for dans mon code comme

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

Ou est-ce sur e des erreurs que je peux ignorer (car il ne casse pas mon code, il fait toujours ce qu'il est censé faire)?

JSLint btw. arrête de valider la première boucle for car je ne définis pas var i en haut de la fonction (c'est pourquoi je suis passé à JSHint en premier lieu). Donc, selon l'exemple de cette question: Dois-je utiliser la validation JavaScript JSLint ou JSHint? - Je dois quand même utiliser des boucles for comme celle-ci pour confirmer JSLint:

...
var i;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
...
//for-loop 2
for (i = 0; ...; i++) { ... }

Cela me semble également bien, car de cette façon, je devrais éviter les erreurs dans JSLint et JSHint. Mais ce dont je ne suis pas sûr, c'est de savoir si je devrais utiliser une variable différente pour chaque boucle for comme ceci:

...
var i, j;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
//for-loop 2
for (j = 0; ...; j++) { ... }

Y a-t-il donc une meilleure pratique pour cela ou pourrais-je simplement utiliser l'un des codes ci-dessus, ce qui signifie que je choisis "ma" meilleure pratique?

61
TimG

Étant donné que les déclarations de variables sont hissées au sommet de la portée dans laquelle elles apparaissent, l'interpréteur interprétera efficacement les deux versions de la même manière. Pour cette raison, JSHint et JSLint suggèrent de déplacer les déclarations hors de l'initialiseur de boucle.

Le code suivant ...

for (var i = 0; i < 10; i++) {}
for (var i = 5; i < 15; i++) {}

... est effectivement interprété comme suit:

var i;
for (i = 0; i < 10; i++) {}
for (i = 5; i < 15; i++) {}

Notez qu'il n'y a vraiment qu'une seule déclaration de i et plusieurs affectations - vous ne pouvez pas vraiment "redéclarer" une variable dans la même portée.

Pour réellement répondre à votre question ...

y a-t-il une meilleure pratique pour cela ou pourrais-je simplement utiliser l'un des codes ci-dessus?

Il existe différentes opinions sur la meilleure façon de gérer cela. Personnellement, je suis d'accord avec JSLint et je pense que le code est plus clair lorsque vous déclarez toutes les variables ensemble en haut de chaque étendue. Puisque c'est ainsi que le code sera interprété, pourquoi ne pas écrire du code qui ressemble à ce qu'il se comporte?

Mais, comme vous l'avez observé, le code fonctionnera quelle que soit l'approche adoptée, c'est donc un choix de style/convention, et vous pouvez utiliser la forme avec laquelle vous vous sentez le plus à l'aise.

58
James Allardice

Les variables en javascript ont une portée de fonction (pas une portée de bloc).

Lorsque vous définissez var i dans une boucle, il y reste en boucle et aussi dans la fonction ayant cette boucle.

Voir ci-dessous,

function myfun() {
    //for-loop 1
    for (var i = 0; ...; i++) { ... }

    // i is already defined, its scope is visible outside of the loop1.
    // so you should do something like this in second loop.

    for (i = 0; ...; j++) { ... }

    // But doing such will be inappropriate, as you will need to remember
    // if `i` has been defined already or not. If not, the `i` would be global variable.
}
6
Jashwant

Il n'a été mentionné que dans le commentaire de @TSCrowder : Si votre environnement le prend en charge (Firefox, Node.js), dans ES6, vous pouvez utiliser let declaration =

//for-loop 1
for (let i = 0; ...; i++) { ... }

//for-loop 2
for (let i = 0; ...; i++) { ... }

qui limite la portée à l'intérieur de la boucle for . Bonus: JSHint cesse de se plaindre.

6
serv-inc

La raison pour laquelle JSHint montre l'erreur est que, dans JS, la portée des variables est fonction et que les déclarations de variables sont hissées en haut de la fonction.

Dans Firefox, vous pouvez utiliser le mot clé let pour définir la portée du bloc, mais il n'est actuellement pas pris en charge par les autres navigateurs.

Le mot clé let est inclus dans la spécification ECMAScript 6.

4
Corneliu

Je sais que cette question a été répondue, mais si vous voulez du super pour les boucles, écrivez-les comme ceci:

var names = ['alex','john','paul','nemo'],
    name = '',
    idx = 0,
    len = names.length;

for(;idx<len;++idx)
{
    name = names[idx];
    // do processing...
}

Quelques choses se passent ici ...

  1. La longueur du tableau est stockée dans len. Cela empêche JS d'évaluer names.length chaque itération

  2. L'incrément idx est un PRE-INCREMENT (par exemple ++ idx NOT idx ++). Les pré-incréments sont nativement plus rapides que les post-incréments.

  3. Le stockage d'une référence à name. Ceci est facultatif mais recommandé si vous utilisez beaucoup la variable name. Chaque appel à names[idx] nécessite de trouver l'index dans le tableau. Que cette recherche soit une recherche linéaire, une recherche arborescente ou une table de hachage, la recherche est toujours en cours. Conservez donc une référence dans une autre variable pour réduire les recherches.

Enfin, ce n'est que ma préférence personnelle, et je n'ai aucune preuve ni aucun avantage en termes de performances. Cependant, j'aime toujours initialiser les variables au type qu'elles vont être, par exemple name = '',.

4
AlexMorley-Finch

La meilleure pratique consiste à réduire la portée des variables, donc la meilleure façon de déclarer la variable d'itération pour les boucles est

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

Je connais la portée des variables déclarées avec var mais je prends ici la lisibilité du code.

1
Nikolay Kostov