Pregunta javascript 'let' y 'var' en for-loops


En mi búsqueda de números concretos para respaldar el uso del const palabra clave en Javascript, me encontré con una comparación de rendimiento entre los tres tipos de declaración de variables var, let y const. No me gustó la configuración de la prueba, así que creé uno simplificado.

No esperaba mucha diferencia y Firefox estuvo a la altura de mis expectativas:

jsPerf results on Firefox 52

Pero en Chromium sucedió algo extraño:

jsPerf results on Chrome 57

No solo todos los resultados de las pruebas son significativamente más bajos let dentro del lazo se descompone a una fracción de la velocidad.

Decidí ejecutar las pruebas en Browserstack para asegurarme de que no se tratara de mi peculiar configuración de Linux. Lo mismo sucede allí con Firefox 53 y Chrome 58 en Windows 10. Incluso probé el algo más viejo Chrome 50 y obtuve el mismo comportamiento.

Que esta pasando? ¿Es un error?

EDITAR: Algunos comentaron que probablemente el bucle está optimizado, ya que no está haciendo nada. Para mostrar, que este no es el caso, cambié la prueba.


10
2018-05-08 12:36


origen


Respuestas:


Cuando usas let el cuerpo del bucle for debe crear un nuevo alcance para manejar la vida útil correcta para la variable de bucle, sin embargo, en muchos casos, es posible optimizar el código adicional y el tiempo de ejecución. Por ejemplo, considere este código:

let sum = 0;
let fns = [];
for (let i=0; i < 1000; i++) {
  function foo() { sum += i; }

  fns.push(foo);

}

Cuando lo ejecuta a través de babeljs, puede ver que el código ES5 equivalente que produce incluye una llamada a función para preservar las vidas útiles correctas de las variables:

var sum = 0;
var fns = [];

var _loop = function _loop(i) {
  function foo() {
    sum += i;
  }

  fns.push(foo);
};

for (var i = 0; i < 1000; i++) {
  _loop(i);
}

Sin embargo, babel es lo suficientemente inteligente como para que, si no haces nada que requiera extender la vida útil de la variable de bucle, simplemente use una corriente for lazo con el cuerpo en línea. Entonces tu código:

for (let i=0; i < 1000; i++) {
  true;
}

se puede demostrar que es exactamente equivalente a:

for (var i=0; i < 1000; i++) {
  true;
}

Supongo que algo muy similar ocurre internamente en Chrome, pero aún no han optimizado los casos en los que no tienen que mantener viva la variable de bucle.

Sería interesante ver cómo el código que utilicé en la parte superior de este ejemplo se compara en Firefox y Chrome, ya que sospecho que ambos deberían terminar de manera similar lenta. Debe tener cuidado con los tiempos, como bucles vacíos, ya que los resultados pueden ser sesgados por la optimización mucho más de lo normal para el código real.


2
2018-05-08 12:45



Es porque la palabra clave let es algo nueva en la especificación y solo es aplicable al alcance local. En Chrome, parece que todavía no está optimizado, pero eso solo debería ser una cuestión de tiempo.


0
2018-05-08 12:42