sirve - ¿Cuál es la diferencia entre usar "let" y "var" para declarar una variable en JavaScript?
para que sirve let javascript (27)
ECMAScript 6 introdujo la declaración let
. He oído que se describe como una variable "local", pero aún no estoy seguro de cómo se comporta de manera diferente a la palabra clave var
.
¿Cuáles son las diferencias? ¿Cuándo debe let
usar sobre var
?
let
Alcance del bloque
Las variables declaradas con la palabra clave let
tienen un ámbito de bloque, lo que significa que están disponibles solo en el bloque en el que se declararon.
En el nivel superior (fuera de una función)
En el nivel superior, las variables declaradas utilizando no let
crear propiedades en el objeto global.
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined
Dentro de una funcion
Dentro de una función (pero fuera de un bloque), tenga el mismo alcance que var
.
(() => {
var functionScopedVariable = 42;
let blockScopedVariable = 43;
console.log(functionScopedVariable); // 42
console.log(blockScopedVariable); // 43
})();
console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Dentro de un bloque
Las variables declaradas usando let
dentro de un bloque no se pueden acceder fuera de ese bloque.
{
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
}
console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Dentro de un bucle
Las variables declaradas con bucles de entrada pueden ser referenciadas solo dentro de ese bucle.
for (var i = 0; i < 3; i++) {
var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4
for (let k = 0; k < 3; k++) {
let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.
Bucles con cierres
Si utiliza let
lugar de var
en un bucle, con cada iteración obtendrá una nueva variable. Eso significa que puede usar un cierre de forma segura dentro de un bucle.
// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0);
}
Zona muerta temporal
Debido a la zona muerta temporal , no se puede acceder a las variables declaradas utilizando let
antes de declararlas. Intentar hacerlo arroja un error.
console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;
No re-declarar
No puedes declarar la misma variable varias veces usando let
. Tampoco puede declarar una variable usando let
con el mismo identificador que otra variable que fue declarada usando var
.
var a;
var a; // Works fine.
let b;
let b; // SyntaxError: Identifier ''b'' has already been declared
var c;
let c; // SyntaxError: Identifier ''c'' has already been declared
const
const
es bastante similar a let
que let
de ámbito de bloques y tiene TDZ. Hay, sin embargo, dos cosas que son diferentes.
Sin reasignación
La variable declarada usando const
no puede ser reasignada.
const a = 42;
a = 43; // TypeError: Assignment to constant variable.
Tenga en cuenta que no significa que el valor sea inmutable. Sus propiedades todavía se pueden cambiar.
const obj = {};
obj.a = 42;
console.log(obj.a); // 42
Si desea tener un objeto inmutable, debe usar Object.freeze()
.
Se requiere inicializador
Siempre debe especificar un valor al declarar una variable usando const
.
const a; // SyntaxError: Missing initializer in const declaration
Función VS ámbito de bloque:
La principal diferencia entre var
y let
es que las variables declaradas var
son función de ámbito . Mientras que las funciones declaradas let
son de ámbito de bloque . Por ejemplo:
function testVar () {
if(true) {
var foo = ''foo'';
}
console.log(foo);
}
testVar();
// logs ''foo''
function testLet () {
if(true) {
let bar = ''bar'';
}
console.log(bar);
}
testLet();
// reference error
// bar is scoped to the block of the if statement
variables con var
:
Cuando testVar
se llama a la primera función, la variable foo, declarada con var
, sigue siendo accesible fuera de la if
declaración. Esta variable foo
estaría disponible en cualquier parte dentro del alcance de la testVar
función .
variables con let
:
Cuando testLet
se llama a la segunda función, la barra de variables, declarada con let
, solo es accesible dentro de la if
declaración. Debido a que las variables declaradas con let
son de ámbito bloque (donde un bloque es el código entre corchetes, por ejemplo if{}
, for{}
, function{}
).
let
las variables no se echan
Otra diferencia entre var
y let
con las variables declaradas con let
no conseguir elevadas . Un ejemplo es la mejor manera de ilustrar este comportamiento:
Las variables con let
no se echan:
console.log(letVar);
let letVar = 10;
// referenceError, the variable doesn''t get hoisted
variables con var
hacer subir:
console.log(varVar);
var varVar = 10;
// logs undefined, the variable gets hoisted
Global let
no se apega a window
:
Una variable declarada con let
en el ámbito global (que es un código que no está en una función) no se agrega como una propiedad en el window
objeto global . Por ejemplo (este código está en alcance global):
var bar = 5;
let foo = 10;
console.log(bar); // logs 5
console.log(foo); // logs 10
console.log(window.bar);
// logs 5, variable added to window object
console.log(window.foo);
// logs undefined, variable not added to window object
¿Cuándo debería
let
ser usado másvar
?
Utilizar let
más var
cada vez que pueda, ya que es simplemente cuyo ámbito más específico. Esto reduce los posibles conflictos de nombres que pueden ocurrir al tratar con un gran número de variables. var
se puede usar cuando desea que una variable global esté explícitamente en el window
objeto (siempre considere cuidadosamente si esto es realmente necesario)
¿Cuál es la diferencia entre let
y var
?
- Una variable definida mediante una instrucción
var
se conoce a través de la función en la que está definida, desde el inicio de la función. (*) - Una variable definida utilizando una instrucción
let
solo se conoce en el bloque en el que se define, desde el momento en que se define en adelante. (**)
Para entender la diferencia, considera el siguiente código:
// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here
function loop(arr) {
// i IS known here, but undefined
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( var i = 0; i < arr.length; i++ ) {
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( let j = 0; j < arr.length; j++ ) {
// i IS known here, and has a value
// j IS known here, and has a value
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
}
loop([1,2,3,4]);
for( var k = 0; k < arr.length; k++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
};
for( let l = 0; l < arr.length; l++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS known here, and has a value
};
loop([1,2,3,4]);
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
Aquí, podemos ver que nuestra variable j
solo se conoce en el primer bucle for, pero no antes y después. Sin embargo, nuestra variable i
es conocida en toda la función.
Además, tenga en cuenta que las variables de ámbito de bloque no se conocen antes de declararse porque no están elevadas. Tampoco está permitido volver a declarar la misma variable de ámbito de bloque dentro del mismo bloque. Esto hace que las variables de ámbito de bloque sean menos propensas a errores que las variables de alcance global o funcional, que se elevan y no producen errores en el caso de declaraciones múltiples.
¿Es seguro usarlo hoy?
Algunas personas argumentarán que en el futuro SOLAMENTE usaremos declaraciones de dejar y que las declaraciones de var serán obsoletas. El gurú de JavaScript, Kyle Simpson, escribió un artículo muy detallado sobre por qué no es así .
Hoy, sin embargo, ese definitivamente no es el caso. De hecho, necesitamos preguntarnos si es seguro usar la declaración let
. La respuesta a esa pregunta depende de su entorno:
Si está escribiendo el código de JavaScript del lado del servidor ( Node.js ), puede usar la instrucción
let
forma segura.Si está escribiendo un código de JavaScript del lado del cliente y usa un transpiler (como Traceur ), puede usar de manera segura la declaración
let
, sin embargo, es probable que su código sea todo menos óptimo con respecto al rendimiento.Si está escribiendo el código JavaScript del lado del cliente y no utiliza un transpiler, debe considerar la compatibilidad con el navegador.
Hoy, 8 de junio de 2018, todavía hay algunos navegadores que no admiten let
!
Cómo realizar un seguimiento de la compatibilidad del navegador
Para obtener una descripción actualizada de qué navegadores son compatibles con la declaración de let
en el momento de leer esta respuesta, consulte esta página Can I Use
?
(*) Las variables de alcance global y funcional pueden inicializarse y usarse antes de declararse porque las variables de JavaScript están hoisted . Esto significa que las declaraciones están siempre en la parte superior del alcance.
(**) Las variables de ámbito de bloque no son elevadas.
A la respuesta aceptada le falta un punto:
{
let a = 123;
};
console.log(a); // ReferenceError: a is not defined
Aquí hay un ejemplo de la diferencia entre los dos (el soporte acaba de comenzar para Chrome):
Como puede ver, la variable var j
sigue teniendo un valor fuera del alcance del bucle for (Ámbito del bloque), pero la variable let i
no está definida fuera del alcance del bucle for.
"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
console.log(j);
}
console.log(j);
console.log("let:");
for (let i = 0; i < 2; i++) {
console.log(i);
}
console.log(i);
Aquí hay un ejemplo para agregar a lo que otros ya han escrito. Supongamos que desea crear una matriz de funciones, funciones adderFunctions
, donde cada función toma un solo argumento de Número y devuelve la suma del argumento y el índice de la función en la matriz. Tratar de generar adderFunctions
con un bucle usando la palabra clave var
no funcionará de la manera que alguien podría esperar ingenuamente:
// An array of adder functions.
var adderFunctions = [];
for (var i = 0; i < 1000; i++) {
// We want the function at index i to add the index to its argument.
adderFunctions[i] = function(x) {
// What is i bound to here?
return x + i;
};
}
var add12 = adderFunctions[12];
// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000
// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true
El proceso anterior no genera la matriz de funciones deseada porque el alcance de i
extiende más allá de la iteración del bloque for
en el que se creó cada función. En cambio, al final del bucle, la i
en el cierre de cada función se refiere al valor de i
al final del bucle (1000) para cada función anónima en adderFunctions
. Esto no es lo que queríamos en absoluto: ahora tenemos una matriz de 1000 funciones diferentes en la memoria con exactamente el mismo comportamiento. Y si posteriormente actualizamos el valor de i
, la mutación afectará a todas las adderFunctions
.
Sin embargo, podemos volver a intentarlo utilizando la palabra clave let
:
// Let''s try this again.
// NOTE: We''re using another ES6 keyword, const, for values that won''t
// be reassigned. const and let have similar scoping behavior.
const adderFunctions = [];
for (let i = 0; i < 1000; i++) {
// NOTE: We''re using the newer arrow function syntax this time, but
// using the "function(x) { ..." syntax from the previous example
// here would not change the behavior shown.
adderFunctions[i] = x => x + i;
}
const add12 = adderFunctions[12];
// Yay! The behavior is as expected.
console.log(add12(8) === 20); // => true
// i''s scope doesn''t extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined
Esta vez, i
es rebote en cada iteración del bucle for
. Cada función ahora mantiene el valor de i
en el momento de la creación de la función, y las funciones de adderFunctions
comportan como se espera.
Ahora, la imagen mezcla los dos comportamientos y probablemente verá por qué no se recomienda mezclar las nuevas let
y const
con las var
más antiguas en el mismo script. Hacerlo puede resultar en un código espectacularmente confuso.
const doubleAdderFunctions = [];
for (var i = 0; i < 1000; i++) {
const j = i;
doubleAdderFunctions[i] = x => x + i + j;
}
const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];
// It''s not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true
No dejes que esto te pase a ti. Usa una plantilla.
NOTA: Este es un ejemplo de enseñanza destinado a demostrar el comportamiento
var
/let
en bucles y con cierres de funciones que también serían fáciles de entender. Esta sería una manera terrible de sumar números. Pero la técnica general de captura de datos en cierres de funciones anónimas puede encontrarse en el mundo real en otros contextos. YMMV.
Aquí hay una explicación de la palabra clave let
con algunos ejemplos.
Dejamos los trabajos muy parecidos a var. La principal diferencia es que el alcance de una variable var es la función de cierre completa.
Esta tabla en Wikipedia muestra qué navegadores son compatibles con Javascript 1.7.
Tenga en cuenta que solo los navegadores Mozilla y Chrome lo admiten. IE, Safari, y potencialmente otros no.
Hay algunas diferencias sutiles: let
alcance se comporte más como el alcance variable en más o menos otros idiomas.
Por ejemplo, se dirige al bloque adjunto, no existen antes de que se declaren, etc.
Sin embargo, vale la pena señalar que let
solo una parte de las nuevas implementaciones de Javascript y que tiene diversos grados de compatibilidad con el navegador .
La diferencia es el alcance. var
encuentra dentro del alcance del bloque de función más cercano y se le asigna el alcance al bloque de cierre más cercano, que puede ser más pequeño que un bloque de función. Ambos son globales si están fuera de cualquier bloque.
Además, las variables declaradas con let
no son accesibles antes de que se declaren en su bloque adjunto. Como se ve en la demostración, esto lanzará una excepción ReferenceError.
Demo :
var html = '''';
write(''#### global ####/n'');
write(''globalVar: '' + globalVar); //undefined, but visible
try {
write(''globalLet: '' + globalLet); //undefined, *not* visible
} catch (exception) {
write(''globalLet: exception'');
}
write(''/nset variables'');
var globalVar = ''globalVar'';
let globalLet = ''globalLet'';
write(''/nglobalVar: '' + globalVar);
write(''globalLet: '' + globalLet);
function functionScoped() {
write(''/n#### function ####'');
write(''/nfunctionVar: '' + functionVar); //undefined, but visible
try {
write(''functionLet: '' + functionLet); //undefined, *not* visible
} catch (exception) {
write(''functionLet: exception'');
}
write(''/nset variables'');
var functionVar = ''functionVar'';
let functionLet = ''functionLet'';
write(''/nfunctionVar: '' + functionVar);
write(''functionLet: '' + functionLet);
}
function blockScoped() {
write(''/n#### block ####'');
write(''/nblockVar: '' + blockVar); //undefined, but visible
try {
write(''blockLet: '' + blockLet); //undefined, *not* visible
} catch (exception) {
write(''blockLet: exception'');
}
for (var blockVar = ''blockVar'', blockIndex = 0; blockIndex < 1; blockIndex++) {
write(''/nblockVar: '' + blockVar); // visible here and whole function
};
for (let blockLet = ''blockLet'', letIndex = 0; letIndex < 1; letIndex++) {
write(''blockLet: '' + blockLet); // visible only here
};
write(''/nblockVar: '' + blockVar);
try {
write(''blockLet: '' + blockLet); //undefined, *not* visible
} catch (exception) {
write(''blockLet: exception'');
}
}
function write(line) {
html += (line ? line : '''') + ''<br />'';
}
functionScoped();
blockScoped();
document.getElementById(''results'').innerHTML = html;
<pre id="results"></pre>
Global:
Son muy similares cuando se usan así fuera de un bloque de función.
let me = ''go''; // globally scoped
var i = ''able''; // globally scoped
Sin embargo, las variables globales definidas con let
no se agregarán como propiedades en el objeto de window
global como las definidas con var
.
console.log(window.me); // undefined
console.log(window.i); // ''able''
Función:
Son idénticos cuando se usan así en un bloque de función.
function ingWithinEstablishedParameters() {
let terOfRecommendation = ''awesome worker!''; //function block scoped
var sityCheerleading = ''go!''; //function block scoped
}
Bloquear:
Aquí está la diferencia. let
solo es visible en el bucle for()
y var
es visible para toda la función.
function allyIlliterate() {
//tuce is *not* visible out here
for( let tuce = 0; tuce < 5; tuce++ ) {
//tuce is only visible in here (and in the for() parentheses)
//and there is a separate tuce variable for each iteration of the loop
}
//tuce is *not* visible out here
}
function byE40() {
//nish *is* visible out here
for( var nish = 0; nish < 5; nish++ ) {
//nish is visible to the whole function
}
//nish *is* visible out here
}
Redeclaración:
Suponiendo un modo estricto, var
le permitirá volver a declarar la misma variable en el mismo ámbito. Por otro lado, let
haremos:
''use strict'';
let me = ''foo'';
let me = ''bar''; // SyntaxError: Identifier ''me'' has already been declared
''use strict'';
var me = ''foo'';
var me = ''bar''; // No problem, `me` is replaced.
La principal diferencia es la diferencia de alcance , mientras que let solo puede estar disponible dentro del alcance que está declarado, como en for loop, por ejemplo, se puede acceder a var fuera del loop. De la documentación en MDN (ejemplos también de MDN):
let le permite declarar variables que están limitadas en su alcance al bloque, la declaración o la expresión en la que se utiliza. Esto es diferente a la palabra clave var , que define una variable globalmente, o localmente a una función completa, independientemente del alcance del bloque.
Las variables declaradas por let tienen como su alcance el bloque en el que están definidas, así como en cualquier sub-bloque contenido. De esta manera, dejemos que los trabajos se parezcan mucho a la var . La principal diferencia es que el alcance de una variable var es la función de cierre completa:
function varTest() {
var x = 1;
if (true) {
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}`
En el nivel superior de programas y funciones, a diferencia de var , no crea una propiedad en el objeto global. Por ejemplo:
var x = ''global'';
let y = ''global'';
console.log(this.x); // "global"
console.log(this.y); // undefined
Cuando se utiliza dentro de un bloque, permite limitar el alcance de la variable a ese bloque. Note la diferencia entre var cuyo alcance está dentro de la función donde se declara.
var a = 1;
var b = 2;
if (a === 1) {
var a = 11; // the scope is global
let b = 22; // the scope is inside the if-block
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
Además, no olvide que es la función ECMA6, por lo que aún no está totalmente soportada, así que es mejor que siempre la transfiera a ECMA5 utilizando Babel, etc. Para obtener más información sobre el sitio web babel visite
ECMAScript 6 agregó una palabra clave más para declarar otras variables "const" que no sean "let".
El objetivo principal de la introducción de "let" y "const" sobre "var" es tener un ámbito de bloque en lugar del tradicional léxico. Este artículo explica muy brevemente la diferencia entre "var" y "let" y también cubre la discusión sobre "const" .
let
Es interesante, porque nos permite hacer algo como esto:
(() => {
var count = 0;
for (let i = 0; i < 2; ++i) {
for (let i = 0; i < 2; ++i) {
for (let i = 0; i < 2; ++i) {
console.log(count++);
}
}
}
})();
Lo que resulta en el conteo [0, 7].
Mientras
(() => {
var count = 0;
for (var i = 0; i < 2; ++i) {
for (var i = 0; i < 2; ++i) {
for (var i = 0; i < 2; ++i) {
console.log(count++);
}
}
}
})();
Solo cuenta [0, 1].
let
también puede ser usado para evitar problemas con los cierres. Enlaza valor nuevo en lugar de mantener una referencia antigua como se muestra en los ejemplos a continuación.
for(var i = 1; i < 6; i++) {
document.getElementById(''my-element'' + i)
.addEventListener(''click'', function() { alert(i) })
}
El código anterior demuestra un problema clásico de cierre de JavaScript. La referencia a la variable i
se almacena en el cierre del controlador de clic, en lugar del valor real de i
.
Cada controlador de un solo clic se referirá al mismo objeto porque solo hay un objeto de contador que contiene 6, por lo que obtiene seis en cada clic.
La solución general es envolver esto en una función anónima y pasar i
como argumento. Tales problemas también se pueden evitar ahora utilizando let
lugar de var
como se muestra en el código a continuación.
DEMO (Probado en Chrome y Firefox 50)
''use strict'';
for(let i = 1; i < 6; i++) {
document.getElementById(''my-element'' + i)
.addEventListener(''click'', function() { alert(i) })
}
var
Es una variable de alcance global (elevable).
let
y const
es ámbito de bloque.
test.js
{
let l = ''let'';
const c = ''const'';
var v = ''var'';
v2 = ''var 2'';
}
console.log(v, this.v);
console.log(v2, this.v2);
console.log(l); // ReferenceError: l is not defined
console.log(c); // ReferenceError: c is not defined
Cuando usas let
La let
palabra clave adjunta la declaración de variable al alcance de cualquier bloque (generalmente un { .. }
par) en el que se encuentra. En otras palabras, let
secuestra de forma implícita el alcance de cualquier bloque para su declaración de variable.
let
no se puede acceder a las variables en el window
objeto porque no se puede acceder a ellas globalmente.
function a(){
{ // this is the Max Scope for let variable
let x = 12;
}
console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined
Cuando usas var
var
y las variables en ES5 tienen ámbitos en las funciones, lo que significa que las variables son válidas dentro de la función y no fuera de la función en sí.
var
Se puede acceder a las variables en el window
objeto porque no se puede acceder a ellas globalmente.
function a(){ // this is the Max Scope for var variable
{
var x = 12;
}
console.log(x);
}
a(); // 12
Si quieres saber más sigue leyendo a continuación.
una de las preguntas de entrevista más famosas sobre el alcance también puede ser suficiente con el uso exacto de let
y var
como se muestra a continuación;
Cuando usas let
for (let i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 0 to 9, that is literally AWW!!!
},
100 * i);
}
Esto se debe a que, al usar let
, para cada iteración de bucle, la variable tiene un ámbito y tiene su propia copia.
Cuando usas var
for (var i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 10 times 10
},
100 * i);
}
Esto se debe a que, al usar var
, para cada iteración de bucle, la variable tiene un ámbito y tiene una copia compartida.
Como se ha mencionado más arriba:
La diferencia es el alcance.
var
tiene el alcance del bloque de función más cercano y ellet
alcance del bloque de cierre más cercano , que puede ser más pequeño que un bloque de función. Ambos son globales si están fuera de cualquier bloque. Veamos un ejemplo:
Ejemplo 1:
En mis dos ejemplos tengo una función myfunc
. myfunc
contiene una variable myvar
igual a 10. En mi primer ejemplo, compruebo si myvar
es igual a 10 ( myvar==10
). En caso afirmativo, nuevamente declaro una variable myvar
(ahora tengo dos variables myvar) usando var
palabras clave y le asigno un nuevo valor (20) En la siguiente línea imprimo su valor en mi consola. Después del bloque condicional, de nuevo imprimo el valor de myvar
en mi consola. Si nos fijamos en la salida de myfunc
, myvar
tiene valor igual a 20.
Ejemplo 2: en mi segundo ejemplo, en lugar de usar var
palabras clave en mi bloque condicional, declaro myvar
usar let
palabras clave. Ahora cuando llamo myfunc
me sale dos salidas diferentes: myvar=20
y myvar=10
.
Así que la diferencia es muy simple, es decir, su alcance.
Este artículo define claramente la diferencia entre var, let y const.
const
es una señal de que el identificador no será reasignado.
let
, es una señal de que la variable puede ser reasignada, como un contador en un bucle o un intercambio de valores en un algoritmo. También indica que la variable se usará solo en el bloque en el que se define, lo que no siempre es la función que contiene todo.
var
Ahora es la señal más débil disponible cuando define una variable en JavaScript. La variable puede o no ser reasignada, y la variable puede o no ser utilizada para una función completa, o solo para el propósito de un bloque o bucle.
https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b
Que las dos funciones siguientes muestren la diferencia:
function varTest() {
var x = 31;
if (true) {
var x = 71; // Same variable!
console.log(x); // 71
}
console.log(x); // 71
}
function letTest() {
let x = 31;
if (true) {
let x = 71; // Different variable
console.log(x); // 71
}
console.log(x); // 31
}
También parece que, al menos en Visual Studio 2015, TypeScript 1.5, "var" permite múltiples declaraciones del mismo nombre de variable en un bloque, y "let" no.
Esto no generará un error de compilación:
var x = 1;
var x = 2;
Esta voluntad:
let x = 1;
let x = 2;
Ahora creo que hay un mejor alcance de las variables a un bloque de declaraciones utilizando let
:
function printnums()
{
// i is not accessible here
for(let i = 0; i <10; i+=)
{
console.log(i);
}
// i is not accessible here
// j is accessible here
for(var j = 0; j <10; j++)
{
console.log(j);
}
// j is accessible here
}
Creo que la gente comenzará a usar Let here after para que tengan un alcance similar en JavaScript como otros lenguajes, Java, C #, etc.
Las personas que no tienen una comprensión clara sobre el alcance en JavaScript solían cometer el error antes.
No se soporta el izamiento utilizando let
.
Con este enfoque se eliminan los errores presentes en JavaScript.
Refiérase a ES6 en profundidad: deje que consten para entenderlo mejor.
Algunos hacks con let
:
1.
let statistics = [16, 170, 10];
let [age, height, grade] = statistics;
console.log(height)
2.
let x = 120,
y = 12;
[x, y] = [y, x];
console.log(`x: ${x} y: ${y}`);
3.
let node = {
type: "Identifier",
name: "foo"
};
let { type, name, value } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined
let node = {
type: "Identifier"
};
let { type: localType, name: localName = "bar" } = node;
console.log(localType); // "Identifier"
console.log(localName); // "bar"
Getter y setter con let
:
let jar = {
numberOfCookies: 10,
get cookies() {
return this.numberOfCookies;
},
set cookies(value) {
this.numberOfCookies = value;
}
};
console.log(jar.cookies)
jar.cookies = 7;
console.log(jar.cookies)
Anteriormente, solo había dos ámbitos en JavaScript, es decir, funcional y global. Con '' let
'' palabra clave JavaScript ahora ha introducido block-level
variables.
Para tener una comprensión completa de la palabra clave ''let'', ES6: la palabra clave ''let'' para declarar la variable en JavaScript ayudará.
La diferencia está en el scope de las variables declaradas con cada una.
En la práctica, hay una serie de consecuencias útiles de la diferencia en el alcance:
-
let
las variables solo son visibles en su bloque de cierre más cercano ({ ... }
). -
let
las variables solo se pueden usar en líneas de código que se producen después de que se declara la variable (¡aunque se hayan izado !) -
let
Las variables no pueden ser redeclaradas por un posteriorvar
olet
. - Las
let
variables globales no se agregan alwindow
objeto global . -
let
Las variables son fáciles de usar con cierres (no causan condiciones de carrera ).
Las restricciones impuestas let
reducen la visibilidad de las variables y aumentan la probabilidad de que las colisiones de nombres inesperadas se encuentren pronto. Esto facilita el seguimiento y el razonamiento de las variables, incluida su reachability (lo que ayuda a recuperar la memoria no utilizada).
En consecuencia, let
es menos probable que las variables causen problemas cuando se usan en programas grandes o cuando los marcos desarrollados de forma independiente se combinan de formas nuevas e inesperadas.
var
aún puede ser útil si está seguro de que desea el efecto de enlace único cuando utiliza un cierre en un bucle (# 5) o para declarar variables globales visibles externamente en su código (# 4). El uso de var
for export puede ser suplantado si export
migra fuera del espacio del transpiler al idioma central.
Ejemplos
1. Sin uso fuera del bloque de cierre más cercano: este bloque de código generará un error de referencia porque el segundo uso se x
produce fuera del bloque donde se declara con let
:
{
let x = 1;
}
console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined".
En contraste, el mismo ejemplo con var
obras.
2. Sin uso antes de la declaración:
este bloque de código lanzará un ReferenceError
código antes de que se pueda ejecutar el código porque x
se usa antes de declararlo
{
x = x + 1; // ReferenceError during parsing: "x is not defined".
let x;
console.log(`x is ${x}`); // Never runs.
}
Por el contrario, el mismo ejemplo var
analiza y ejecuta sin lanzar excepciones.
3. No redeclaración: el siguiente código demuestra que una variable declarada con let
no se puede volver a declarar más adelante:
let x = 1;
let x = 2; // SyntaxError: Identifier ''x'' has already been declared
4. Globales no adheridos a window
:
var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link); // OK
console.log(window.link); // undefined (GOOD!)
console.log(window.button); // OK
5. Fácil uso con cierres: las variables declaradas var
no funcionan bien con cierres dentro de los bucles. Aquí hay un bucle simple que genera la secuencia de valores que la variable i
tiene en diferentes puntos en el tiempo:
for (let i = 0; i < 5; i++) {
console.log(`i is ${i}`), 125/*ms*/);
}
Específicamente, esto produce:
i is 0
i is 1
i is 2
i is 3
i is 4
En JavaScript, a menudo utilizamos variables mucho más tarde que cuando se crean. Cuando demostramos esto retrasando la salida con un cierre pasado a setTimeout
:
for (let i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... la salida permanece sin cambios mientras nos mantengamos let
. Por el contrario, si hubiéramos utilizado en su var i
lugar:
for (var i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... el bucle genera inesperadamente "i is 5" cinco veces:
i is 5
i is 5
i is 5
i is 5
i is 5
Let es una parte de es6. Estas funciones explicarán la diferencia de manera fácil.
function varTest() {
var x = 1;
if (true) {
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
Revisa este enlace en MDN
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// expected output: 2
}
console.log(x);
// expected output: 1
Si leo las especificaciones correctamente, let
afortunadamente también se puede aprovechar para evitar las funciones de auto-invocación usadas para simular miembros exclusivos privados, un patrón de diseño popular que reduce la legibilidad del código, complica la depuración, que no agrega protección de código real ni otro beneficio Deseo de semántica, así que deja de usarlo. /despotricar
var SomeConstructor;
{
let privateScope = {};
SomeConstructor = function SomeConstructor () {
this.someProperty = "foo";
privateScope.hiddenProperty = "bar";
}
SomeConstructor.prototype.showPublic = function () {
console.log(this.someProperty); // foo
}
SomeConstructor.prototype.showPrivate = function () {
console.log(privateScope.hiddenProperty); // bar
}
}
var myInstance = new SomeConstructor();
myInstance.showPublic();
myInstance.showPrivate();
console.log(privateScope.hiddenProperty); // error
Consulte '' Emulación de interfaces privadas ''.
Variable No Levantamientono levantemos todo el alcance del bloque en el que aparecen. Por el contrario,var
podría levantar como se muestra a continuación.{ console.log(cc); // undefined. Caused by hoisting var cc = 23; } { console.log(bb); // ReferenceError: bb is not defined let bb = 23; }
En realidad, Per @ Bergi, ambas
var
ylet
son izados .Recolección de basura
El ámbito de bloqueo de
let
es útil se relaciona con los cierres y la recolección de basura para recuperar memoria. Considerar,function process(data) { //... } var hugeData = { .. }; process(hugeData); var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
La devolución de llamada del controlador de
click
no necesita la variablehugeData
en absoluto. Teóricamente, después de queprocess(..)
ejecuta elprocess(..)
, la enorme estructura de datoshugeData
podría ser recogida de basura. Sin embargo, es posible que algún motor JS aún tenga que mantener esta enorme estructura, ya que la función declick
tiene un cierre en todo el alcance.Sin embargo, el ámbito de bloque puede hacer que esta enorme estructura de datos se recoja en la basura.
function process(data) { //... } { // anything declared inside this block can be garbage collected let hugeData = { .. }; process(hugeData); } var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
let
bucleslet
el bucle pueda volver a vincularlo a cada iteración del bucle, asegurándose de volver a asignarle el valor del final de la iteración del bucle anterior. Considerar,// print ''5'' 5 times for (var i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }
Sin embargo, reemplace
var
conlet
// print 1, 2, 3, 4, 5. now for (let i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }
Debido a
let
creamos un nuevo entorno léxico con esos nombres para a) la expresión inicializadora b) cada iteración (antes de evaluar la expresión de incremento), here hay más detalles.