javascript ''let'' y ''var'' en for-loops
for javascript (2)
En mi búsqueda de números concretos para respaldar el uso de la palabra clave const
en Javascript, tropecé 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é una configuración simplificada .
No esperaba mucha diferencia y Firefox estuvo a la altura de mis expectativas:
Pero en Chromium sucedió algo extraño:
No solo todos los resultados de la prueba son significativamente más bajos sino let
interior del loop 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 ocurre allí con Firefox 53
y Chrome 58
en Windows 10. Incluso probé el Chrome 50
algo más antiguo 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 .
Cuando use let
el cuerpo del bucle for debe crear un nuevo ámbito para manejar la vida útil correcta de 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 un bucle for
normal 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.
Es porque la palabra clave let es algo nueva en la especificación y solo es aplicable al alcance local. En Chrome no parece estar optimizado aún, pero eso solo debería ser una cuestión de tiempo.