web-dev-qa-db-fra.com

Les variables JavaScript déclarent-elles une boucle extérieure ou une boucle intérieure?

En AS3, je pense que vous devriez initialiser toutes les variables en dehors des boucles pour améliorer les performances. Est-ce le cas également avec JavaScript? Quel est le meilleur/plus rapide/la meilleure pratique?

var value = 0;

for (var i = 0; i < 100; i++)
{
    value = somearray[i];
}

ou

for (var i = 0 ; i < 100; i++)
{
    var value = somearray[i];
}
204
davivid

Il y a absolument aucune différence en sens ou en performance, en JavaScript ou en ActionScript.

var est une directive pour l'analyseur et pas une commande exécutée au moment de l'exécution. Si un identifiant particulier a été déclaré var une ou plusieurs fois dans un corps de fonction (*), toute utilisation de cet identifiant dans le bloc se rapportera à la variable locale. Peu importe que value soit déclaré être var dans la boucle, en dehors de la boucle ou les deux.

Par conséquent, vous devriez écrire ce que vous trouvez le plus lisible. Je ne suis pas d'accord avec Crockford sur le fait que placer tous les vars au sommet d'une fonction est toujours la meilleure chose à faire. Dans le cas où une variable est utilisée temporairement dans une section de code, il est préférable de déclarer var dans cette section, de sorte que la section soit autonome et puisse être copiée-collée. Sinon, copiez-collez quelques lignes de code dans une nouvelle fonction pendant le refactoring, sans sélectionner et déplacer séparément le var associé, et vous aurez un global accidentel.

En particulier:

for (var i; i<100; i++)
    do something;

for (var i; i<100; i++)
    do something else;

Crockford vous recommandera de supprimer le second var (ou de supprimer les deux vars et do var i; ci-dessus), et jslint vous en voudra. Mais IMO, il est plus facile de maintenir les deux vars, en conservant tous les codes associés ensemble, au lieu d’avoir un morceau de code supplémentaire, facilement oublié, en haut de la fonction.

Personnellement, j'ai tendance à déclarer comme var la première affectation d'une variable dans une section de code indépendante, qu'il y ait ou non une autre utilisation séparée du même nom de variable dans une autre partie de la même fonction. Pour moi, avoir à déclarer var du tout est une fâcheuse JS indésirable (il aurait été préférable d’avoir des variables par défaut à locales); Je ne vois pas dans mon devoir de reproduire également les limitations de [une ancienne révision de] ANSI C en JavaScript.

(*: autre que dans les corps de fonction imbriqués)

271
bobince

En théorie, cela ne devrait faire aucune différence en JavaScript, car le langage n'a pas de portée de bloc, mais seulement de portée de fonction.

Je ne suis pas sûr de l'argument de performance, mais Douglas Crockford recommande toujours que les instructions var soient les premières instructions du corps de la fonction. Citant de Conventions de code pour le langage de programmation JavaScript :

JavaScript n'a pas de portée de bloc, aussi la définition de variables dans des blocs peut-elle confondre les programmeurs expérimentés avec d'autres langages de la famille C. Définissez toutes les variables en haut de la fonction.

Je pense qu'il a un point, comme vous pouvez le voir dans l'exemple suivant. Déclarer les variables en haut de la fonction ne doit pas inciter les lecteurs à penser que la variable i est maintenue dans la portée du bloc de boucle for:

function myFunction() {
  var i;    // the scope of the variables is very clear

  for (i = 0; i < 10; i++) {
    // ...
  }
}
65
Daniel Vassallo

Le ECMA-/Javascript language hoists toute variable déclarée n'importe où en haut d'une fonction. C’est parce que cette langue a a function scope et est-ce que pas a block scope comme beaucoup d’autres langues C-like.
On l’appelle aussi lexical scope.

Si vous déclarez quelque chose comme

var foo = function(){
    for(var i = 0; i < 10; i++){
    }
};

Ceci amène hoisted à:

var foo = function(){
    var i;
    for(i = 0; i < 10; i++){
    }
}

Cela ne fait donc aucune différence dans les performances (mais corrigez-moi si je me trompe totalement ici).
Un argument bien meilleur pour pas déclarant une variable ailleurs qu'au sommet d'une fonction est lisibilité. Déclarer une variable dans un for-loop pourrait conduire à une hypothèse erronée selon laquelle cette variable ne peut être accédée que dans le corps de la boucle, qui est totalement faux. Enfait, vous pouvez accéder à cette variable n'importe où dans l'étendue actuelle.

59
jAndy

L'année prochaine, tous les navigateurs auront des moteurs JS qui précompileront le code, de sorte que la différence de performances (qui provient de l'analyse répétée du même bloc de code et de l'exécution de l'affectation) deviendrait négligeable.

En outre, n'optimisez jamais les performances sauf si vous devez le faire. Garder les variables près de l'endroit où vous en avez besoin la première fois garde votre code propre. Du côté négatif, les personnes habituées aux langues avec des portées de bloc peuvent être confondues.

13
Aaron Digulla

Je viens de faire un simple test sous Chrome. Essayez le violon dans votre navigateur et affichez les résultats.

  var count = 100000000;
    var a = 0;
    console.log(new Date());

    for (var i=0; i<count; i++) {
      a = a + 1
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
      a = a + 1;
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
        var x;
        x = x + 1;
    }

    console.log(new Date());

Le résultat est que le dernier test dure environ 8 secondes et que les 2 précédents ne durent que 2 secondes environ. De manière très répétable et quel que soit l'ordre.

Donc, cela me prouve qu'il faut toujours déclarer les vars en dehors de la boucle. Le cas curieux pour moi est le premier où je déclare i dans l’instruction for (). Celui-ci semble être aussi rapide que le 2e test où je pré-déclare l'index.

4
mkoistinen

Une autre considération, maintenant que nous avons let et const dans ES2015, est que vous pouvez maintenant définir des variables de manière spécifique pour le bloc de boucle. Donc, à moins que vous n'ayez besoin de la même variable en dehors de la boucle (ou si chaque itération dépend d'une opération effectuée sur cette variable lors de l'itération précédente), il est probablement préférable de procéder ainsi:

for (let i = 0; i < 100; i++) {
    let value = somearray[i];
    //do something with `value`
}
3
Matt Browne

JavaScript est un langage écrit en bas en C ou C++, je ne suis pas très sûr de qui il s'agit. Et l'un de ses objectifs consiste à économiser le temps nécessaire à la gestion de la mémoire interne. Même en C ou C++, vous n'aurez pas à vous demander s'il consomme beaucoup de ressources lorsque des variables sont déclarées dans une boucle. Pourquoi devriez-vous vous en préoccuper en JavaScript?

1
Yan Yang

Cela dépend de ce que vous essayez d’obtenir ... Si value suppose qu’il ne s’agit que d’une variable temporaire à l’intérieur du bloc de boucle, il est beaucoup plus clair d’utiliser la seconde forme. C'est aussi plus logique et prolixe.

0
Crozin

Cela ne fait aucune différence si vous déclarez des variables à l'intérieur ou à l'extérieur de la boucle for. Vous trouverez ci-dessous un exemple de code à tester.

function a() {
   console.log('Function a() starts');
   console.log(new Date());
    var j;
    for (j=0; j<100000000; j++) {
        var x;
        x = x + 1;
    }
    console.log(new Date());
    console.log('Function a() Ends');
}
a()
function b() {
console.log('Function B() starts');
   console.log(new Date());
    var a;
    var j;
    for (j=0; j<100000000; j++) {
      a = a + 1;
    }
    console.log(new Date());
    console.log('Function B() Ends');
}
b()

Les résultats ont montré dans mon cas

Function a() starts
VM121:3 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:9 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:10 Function a() Ends
VM121:14 Function B() starts
VM121:15 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:21 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:22 Function B() Ends

Merci - MyFavs.in

0
myfavs.in