web-dev-qa-db-fra.com

Existe-t-il une différence de performance entre 'let' et 'var' en JavaScript

La différence entre ces deux mots-clés en termes de portée a déjà été discutée en détail ici , mais je me demandais s’il existait une différence de performance entre les deux. Si oui, est-elle négligeable ou à quel moment ça devient significatif?

46
Nickolai

Après avoir testé ceci sur http://jsperf.com , j'ai obtenu les résultats suivants: jsperf est en panne depuis un moment; voir le code de remplacement ci-dessous.

Pour vérifier cela, je vais utiliser le test de performance suivant basé sur cette réponse , qui m'a amené à écrire cette fonction:

/**
 * Finds the performance for a given function
 * function fn the function to be executed
 * int n the amount of times to repeat
 * return array [time for n iterations, average execution frequency (executions per second)]
 */
function getPerf(fn, n) {
  var t0, t1;
  t0 = performance.now();
  for (var i = 0; i < n; i++) {
    fn(i)
  }
  t1 = performance.now();
  return [parseFloat((t1 - t0).toFixed(3)), parseFloat((repeat * 1000 / (t1 - t0)).toFixed(3))];
}

var repeat = 100000000;
var msg = '';

//-------inside a scope------------
var letperf1 = getPerf(function(i) {
  if (true) {
    let a = i;
  }
}, repeat);
msg += '<code>let</code> inside an if() takes ' + letperf1[0] + ' ms for ' + repeat + ' iterations (' + letperf1[1] + ' per sec).<br>'

var varperf1 = getPerf(function(i) {
  if (true) {
    var a = i;
  }
}, repeat);
msg += '<code>var</code> inside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'

//-------outside a scope-----------

var letperf2 = getPerf(function(i) {
  if (true) {}
  let a = i;
}, repeat);
msg += '<code>let</code> outside an if() takes ' + letperf2[0] + ' ms for ' + repeat + ' iterations (' + letperf2[1] + ' per sec).<br>'

var varperf2 = getPerf(function(i) {
  if (true) {}
  var a = i;
}, repeat);
msg += '<code>var</code> outside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'

document.getElementById('out').innerHTML = msg
<output id="out" style="font-family: monospace;white-space: pre-wrap;"></output>

Après avoir testé cela dans Chrome et Firefox, cela montre que let est plus rapide que var, mais uniquement dans une étendue différente de celle de la portée principale d'une fonction. Dans la portée principale, var et let ont à peu près les mêmes performances. Dans IE11 et MS Edge, let et var ont des performances à peu près égales dans les deux cas.

Appuyez sur le gros bouton bleu pour voir par vous-même dans votre navigateur préféré.

Actuellement, let prend en charge uniquement par les nouveaux navigateurs , mais les anciens navigateurs sont encore relativement utilisés, ce qui serait une raison pour ne pas l’utiliser pour le moment. Si vous voulez l'utiliser quelque part où les anciens navigateurs ne fonctionneraient pas autrement, cela ne devrait poser aucun problème.

Edit: réponse remaniée puisque jsperf ne fonctionne pas (voir l'historique des révisions pour l'ancienne version).

45
Joeytje50

FYI; Après Chrome v60, aucune autre régression n'est apparue. var et let sont au coude à coude, var ne gagnant jamais que de moins de 1%. Les scénarios du monde réel donnent parfois à var un avantage dû au levage et à la réutilisation, mais à ce stade, vous comparez des pommes à des oranges, car let vous permet d'éviter ce comportement car la sémantique est différente.

Référence . Firefox, IE et Edge, comme let, vont très bien.

18
TylerY86

Les boucles intérieures let sont nettement plus lentes, voir: https://jsperf.com/let-vs-var-loop

838,602 ± 0,77% 61% plus lent

(function() {

  "use strict";
  var a=0;
  for(let i=0;i<100;i++) {
    a+=i;
  }
})();

vs.

2 136 387 ± 1,09% Le plus rapide

(function() {

  "use strict";
  var a=0;
  for(var i=0;i<100;i++) {
    a+=i;
  }
})();

En effet, lorsque vous utilisez let, la variable est étendue pour chaque itération de boucle. Exemple:

for (let i = 0; i < 10 ; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}

rendements à 

0,1,2,3,4,5,6,7,8,9

en utilisant des rendements variables pour 

10,10,10,10,10,10,10,10,10,10

Si vous voulez avoir le même résultat, mais en utilisant var, vous devez utiliser un IIFE:

for (var i = 0; i < 10; i++) {
  // capture the current state of 'i'
  // by invoking a function with its current value
  (function(i) {
    setTimeout(function() { console.log(i); }, 100 * i);
  })(i);
}

qui est en revanche nettement plus lent que d'utiliser let.

3
Gregor D
$ node --version
v6.0.0
$ node
> timeit = (times, func) => {
     let start = (new Date()).getTime();
     for (let i = 0; i < times; i++) {
       func();
     };
     return (new Date()).getTime() - start;
   };
[Function]
> timeit(1000000, () => {
     let sum = 0;  // <-- here's LET
     for (let i = 0; i < 1000; i++) {
       sum += i;
       if (sum > 1000000) { sum = 0; }
     }
     return sum;
   })
12144
> timeit(1000000, () => {
     var sum = 0;  // <-- here's VAR
     for (let i = 0; i < 1000; i++) {
       sum += i;
       if (sum > 1000000) { sum = 0; }
     }
     return sum;
   })
2459

Même portée (fonction), même code, différence de 5 fois. Résultats similaires en chrome 49.0.2623.75.

1
dchekmarev

var : Déclare une variable, initialisation de la valeur optionnelle. Let est plus rapide en dehors de la portée.

let : Déclare une variable locale avec une portée de bloc. Let est un peu lent dans la boucle intérieure.

Ex:

var a;
a = 1;
a = 2; //re-intilize possibe
var a = 3; //re-declare
console.log(a); //3

let b;
b = 5;
b = 6; //re-intilize possibe
// let b = 7; //re-declare not possible
console.log(b);
0
Srikrushna Pal