web-dev-qa-db-fra.com

Traitement de l'avertissement de déclaration en double pour les variables de boucle

Considérez le code suivant:

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

Tout outil de charpie décent (jslint, jshint ou intégré dans l'IDE) indiquera un avertissement - duplicate declaration of variable i. Cela peut être résolu en utilisant une variable avec un autre nom (k, j) ou en déplaçant la déclaration vers le haut:

var i; // iterator
for (i=0; i<100; i++) {}
for (i=0; i<500; i++) {}

Je n'aime pas les deux variantes - je ne fais généralement pas de déclarations en haut (et même si je le faisais, je ne voudrais pas y voir de variables d'assistance - i, j, k) et vraiment rien de mal ne se passe dans ces exemples pour changer les noms des variables.

Bien que je veuille un énorme avertissement au cas où j'écrirais quelque chose comme ceci:

for (var i=0; i<100; i++) {
    for (var i=0; i<500; i++) {} // now that's bad
}

Quelle est votre approche face à de tels cas?

47
Ilya Tsuryev

JavaScript a de nombreuses constructions qui ressemblent à des constructions bien connues dans d'autres langages informatiques. Il est dangereux pour JavaScript d'interpréter la construction d'une autre comme la plupart des autres langages informatiques.

Si quelqu'un qui ne connaît pas assez bien JavaScript (le cas courant d'ailleurs) voit la construction comme

for (var i=0; i<100; i++) {
    // your code here
}

ou voit la déclaration de la variable dans le bloc

{
    var i;
    //some code
    {
        var j;
        // some code
    }
}

alors la plupart des lecteurs penseront que les variables de niveau bloc seront définies. JavaScript n'a pas de variables au niveau des blocs. Toutes les variables seront interprétées comme le niveau de fonction défini.

Donc je ne définit jamais de variables à l'intérieur du code si le code n'est pas juste un code de test qui sera écrit pendant 5 min seulement. La raison principale est que je ne veux pas écrire de code et utiliser des constructions de langage qui pourraient être mal comprises.

À propos, JSLint trouve la définition des variables à l'intérieur du bloc si mauvais style qu'il arrête le traitement de l'analyse du code. Il n'existe aucune option JSLint qui pourrait modifier ce comportement. Je trouve que le comportement de JSLint n'est pas bon, mais je suis d'accord que la déclaration des variables à l'intérieur de la boucle for est mauvaise car elle sera lue par la plupart des personnes sous forme de code avec local variables de boucle, ce qui est incorrect.

Si tu utilises

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

puis JavaScript déplace toutes les déclarations de variables au début de la fonction pour vous. Donc, le code sera comme

var i = undefined, i = undefined; // duplicate declaration which will be reduced
                                  // to one var i = undefined;

for (i=0; i<100; i++) {
    // your code here
}
// some other code here
for (i=0; i<500; i++) {
    // custom code here
}

Pensez donc aux autres lecteurs du code. N'utilisez aucune construction qui pourrait être interprétée de manière incorrecte.

48
Oleg

let mot-clé est introduit dans javascript 1.7. Veuillez trouver la documentation MDN ici

Remplacement de var par let à l'intérieur de for loop résout le problème et maintenant on peut déclarer une variable locale dans la portée d'une boucle. Découvrez l'explication de la communauté stackoverlow ici: Quelle est la différence entre l'utilisation de "let" et "var" pour déclarer une variable?

Code du futur:

for (let i = 0; i < someVar.length; i++) {
    // do your thing here
}
18
Said Kholov

Je recommande d'inclure vos boucles dans des fonctions auto-exécutables dont les noms vous indiquent ce que fait la boucle. Cela donne effectivement une portée de bloc à la boucle. Par exemple:

var users = response['users']
;(function appendUsers(){
    for (var i = 0; i < users.length; i++) {
        var user      = users[i]
        var userEmail = user['email']
        var userId    = user['id']
        /* etc */ 
    }
})() // appendUsers

Si tu fais ça:

var i
for (i = 0; i < someVar.length; i++) {
    for (i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will not notice.
    }
}

D'autre part:

for (var i = 0; i < someVar.length; i++) {
    for (var i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will warn you about.
    }
}
for (var i = 0; i < yetAnotherVar.length; i++) {
    // It will also warn you about this, but so what?
}

Vous pouvez arrêter d'utiliser i comme itérateur:

for (var companyIndex = 0; companyIndex < companies.length; companyIndex++) {
    var company = companies[companyIndex]
}

Si vous utilisez quand même jQuery, vous pouvez utiliser sa méthode jQuery.each() :

$.each(someVar, function(i, value){
    // etc
})

Vous ne pouvez pas utiliser Array.prototype.forEach() si vous voulez que IE8 et les versions antérieures fonctionnent, sauf si vous ajoutez le code Polyfill ou similaire.

6
Vladimir Kornea

J'ai tendance à utiliser les fonctions intégrées du tableau, telles que map, filter et forEach, évitant ainsi complètement le problème. Cela vous donne également automatiquement des corps de boucle de portée, ce qui est également très utile.

Si leur utilisation ne correspond pas au cas d'utilisation, je recourt généralement à la déclaration top, simplement pour éviter les problèmes que vous avez mentionnés.

2
Exelian

la meilleure pratique ici devrait être un bon style de programmation:

Un programme doit être construit en de courtes fonctions, qui feront une petite tâche. Habituellement, si vous faites une boucle, vous faites quelque chose de spécial qui devrait être intégré à une fonction propre. En fin de compte, chaque fonction a sa propre portée, de sorte que le problème de déclaration de duplication est éliminé.

function myApp() {
    magicLoopAction();
    someOtherMagicStuff();
}
function magicLoopAction() {
    for (var i = 0; i < 42; i++) { 
        // whoopwhoop
    }
}
function someOtherMagicStuff() {
    for (var i = 0; i < 69; i++) { 
        // lint is happy and proud on you
    }
}
1
Putzi San