¿Cuál es la diferencia entre el uso de “dejar” y “var”?
-
11-09-2019 - |
Pregunta
He oído que está descrito como una variable "local", pero todavía no estoy muy seguro de cómo se comporta de manera diferente que la palabra clave var
.
¿Cuáles son las diferencias? ¿Cuándo se debe utilizar sobre let
var
?
Solución
de ámbito
La principal diferencia está Reglas de ámbito. Las variables declaradas por palabra clave var
tiene como alcance el cuerpo de la función inmediata (de ahí el ámbito de la función), mientras que las variables let
están en el ámbito de la inmediata encierra bloque denotado por { }
(de ahí el ámbito de bloque).
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar);
{
let baz = "Bazz";
console.log(baz);
}
console.log(baz); // ReferenceError
}
run();
La razón por la palabra clave let
se introdujo en el lenguaje era el alcance función es confuso y fue una de las principales fuentes de error en Javascript.
Tome un vistazo a este ejemplo de otra pregunta StackOverflow :
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
My value: 3
era la salida a la consola cada vez funcs[j]();
fue invocada desde funciones anónimas estaban ligados a la misma misma variable.
Las personas tenían que crear crear funciones de inmediato invocados para capturar valor correcto de los bucles, sino que también fue cabelludo.
Elevadores
Mientras que las variables declaradas con la palabra clave var
son "izan" a la parte superior del bloque que significa que son accesibles en su ámbito que contiene incluso antes de que se declaran:
function run() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
run();
permiten variables no se inicializan hasta que se evalúe su definición. Acceder a ellos antes de que los resultados de inicialización en un ReferenceError
. Variable dice que está en "zona muerta temporal" desde el principio del bloque hasta que se procesa la inicialización.
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
Creación de la propiedad objeto global
En el nivel superior, let
, a diferencia de var
, no crea una propiedad en el objeto global:
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped
console.log(window.foo); // Foo
console.log(window.bar); // undefined
redeclaración
En el modo estricto, var
le permitirá volver a declarar la misma variable en el mismo ámbito, mientras que let
plantea una SyntaxError.
'use strict';
var foo = "foo1';
var foo = "foo2'; // No problem, 'foo' is replaced.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
Otros consejos
let
también se puede utilizar para evitar problemas con los cierres. Se une valor fresco en lugar de mantener un viejo referencia como se muestra en los ejemplos de abajo.
for(var i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
Código anterior demuestra un problema clásico cierre de JavaScript. se almacena referencia a la variable i
en el cierre clic manipulador, en lugar del valor real de i
.
Cada controlador de clic se referirá al mismo objeto porque sólo hay un contador de objeto que sostiene 6 por lo que obtener seis en cada clic.
Una solución general es la de terminar con esto de una función anónima y pasar i
como argumento. Estas cuestiones también se pueden evitar ahora mediante el uso de let
lugar var
como se muestra en el código de abajo.
(Probado en Chrome y Firefox 50)
for(let i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
¿Cuál es la diferencia entre let
y var
?
- Una variable definida mediante una instrucción
var
es conocida en todo la función se define en, desde el inicio de la función. * - Una variable definida mediante una instrucción
let
sólo se conoce en < strong> el bloque se define en, desde el momento en que se define en adelante. **
Para entender la diferencia, considere 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
A continuación, podemos ver que nuestra j
variable sólo se conoce en el primer bucle, pero no antes y después. Sin embargo, nuestra i
variable se conoce en toda la función.
Además, consideran que las variables de ámbito de bloque no se conocen antes de que se declaran porque no se izan. Tampoco está permitido redeclare el mismo bloque de ámbito variable dentro del mismo bloque. Esto hace que el bloque de ámbito variables menos propenso a errores que las variables de ámbito global o funcionalmente, que se izan y que no producen los errores en caso de múltiples declaraciones.
¿Es seguro utilizar let
hoy?
Algunas personas argumentan que en el futuro vamos a utilizar solamente queden declaraciones y que las declaraciones var quedará obsoleto. JavaScript gurú Kyle Simpson escribió un artículo muy elaborada sobre por qué cree que no será el caso .
Hoy en día, sin embargo, que definitivamente no es el caso. De hecho, necesitamos realmente a preguntarnos si es seguro utilizar la instrucción let
. La respuesta a esa pregunta depende de su entorno:
-
Si va a escribir en el servidor de código JavaScript ( Node.js ), se puede utilizar con seguridad la declaración
let
. -
Si estás escribiendo JavaScript del lado cliente y utilizar un código de transpiler basado en navegador (como < strong> Traceur o babel-independiente ), se puede utilizar con seguridad la declaración
let
, sin embargo, su código es probable que sea cualquier cosa menos óptima con respecto al rendimiento. -
Si estás escribiendo JavaScript del lado cliente y utilizar un código basado transpiler Nodo (como el traceur secuencia de comandos shell o Babel ), se puede utilizar con seguridad la declaración
let
. Y debido a que su navegador sólo sabrá sobre el código transpiled, inconvenientes de rendimiento debe ser limitado. -
Si estás escribiendo JavaScript del lado cliente de código y no utilizar un transpiler, debe tener en cuenta el apoyo del navegador.
Hay todavía algunos navegadores que no soportan
let
en absoluto:
¿Cómo hacer un seguimiento de soporte del navegador
Para una visión general actualizada de los cuales los navegadores soportan la declaración let
en el momento de su lectura de esta respuesta, consulte esta página Can I Use
.
* va de ámbito mundial y funcionalriables se pueden inicializar y utilizados antes de que se declaran las variables JavaScript porque se izadas . Esto significa que las declaraciones son siempre mucho a la parte superior del marco.
** bloque de ámbito variables no se izan
Aquí hay un de la palabra clave let
con algunos ejemplos.
let
funciona muy parecido avar
. La principal diferencia es que el alcance de una variablevar
es toda la función de envolvente
Este tabla de la Wikipedia, que muestra los navegadores soporta Javascript 1.7.
Tenga en cuenta que sólo los navegadores Mozilla y Chrome soportan. IE, Safari, y potencialmente otros no lo hacen.
La respuesta aceptada es que falta un punto:
{
let a = 123;
};
console.log(a); // ReferenceError: a is not defined
let
Ámbito de un bloque
Las variables declaradas usando la palabra clave let
son bloques de ámbito, lo que significa que sólo están disponibles en el bloque en el que fueron declarados.
En el nivel superior (fuera de una función)
En el nivel superior, las variables declaradas usando let
no crean 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 función
Dentro de una función (pero fuera de un bloque), let
tiene 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
variables declaradas usando let
dentro de un bloque no se puede 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 let
en los bucles se puede hacer referencia sólo 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
en lugar de var
en un bucle, con cada iteración se obtiene una nueva variable. Eso significa que usted puede utilizar con seguridad un cierre 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 temporal muertos, las variables declaradas usando let
no se puede acceder antes de que se declaran. Si intenta hacerlo, genera un error.
console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;
No hay re-declarar
No se puede declarar la misma variable varias veces usando let
. Tampoco se puede declarar una variable usando let
con el mismo identificador que otra variable que se declara 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
-bloque es de ámbito y tiene TDZ. Hay, sin embargo, hay dos cosas que son diferentes.
No hay reasignar
variable declarada usando const
no puede ser reasignada.
const a = 42;
a = 43; // TypeError: Assignment to constant variable.
Tenga en cuenta que esto no significa que el valor es inmutable. Sus propiedades se pueden seguir cambiando.
const obj = {};
obj.a = 42;
console.log(obj.a); // 42
Si usted quiere tener un objeto inmutable, debe utilizar Object.freeze()
.
inicializador
Siempre se debe especificar un valor cuando se declara una variable usando const
.
const a; // SyntaxError: Missing initializer in const declaration
A continuación se muestra un ejemplo de la diferencia entre los dos (el apoyo acaba de comenzar para el cromo):
Como se puede ver la variable var j
todavía está teniendo un valor fuera del alcance de bucle (bloque Alcance), pero la variable let i
está definida fuera del alcance de bucle.
"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);
Hay algunas diferencias sutiles - de alcance let
se comporta más como ámbito de las variables hace más o menos en cualquier otro idioma.
por ejemplo. Se ámbitos para el bloque que lo contiene, No existen antes de que sean declarados, etc.
Sin embargo vale la pena señalar que let
es sólo una parte de las implementaciones más recientes de Javascript y tiene diversos grados de .
-
Levantamiento de variable nolet
habrá no izar a todo el ámbito del bloque que aparecen. Por el contrario,var
podría izar como 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, por @Bergi, Tanto
var
ylet
se izan . -
Garbage Collection
Bloque alcance de
let
es útil refiere a cierres y recolección de basura para reclamar memoria. Considere,function process(data) { //... } var hugeData = { .. }; process(hugeData); var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
El manejador de devolución de llamada
click
no necesita la variablehugeData
en absoluto. En teoría, después de carrerasprocess(..)
, la enorme estructura de datoshugeData
podría ser basura recogida. Sin embargo, es posible que algunos motores de JS todavía tendrá que mantener esta enorme estructura, ya que la funciónclick
tiene un cierre en todo el ámbito de aplicación.Sin embargo, el ámbito de bloque puede hacer esta enorme estructura de datos para basura recogida.
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){ //.... });
-
bucles
let
let
en el bucle puede re-une que para cada iteración del bucle, asegurándose de volver a asignarle el valor a partir del final de la iteración anterior. Considere,// 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
let
crear un nuevo entorno léxico con esos nombres para: a) la expresión initialiser b) cada iteración (Anteriormente: para evaluar la expresión de incremento), más detalles están aquí .
La principal diferencia es la alcance diferencia, mientras que deja puede ser sólo está disponible dentro de la alcance es declarado, al igual que en el bucle for, < strong> var se puede acceder fuera del bucle, por ejemplo. A partir de la documentación de MDN (ejemplos también de MDN):
dejas le permite declarar las variables que están limitados en su alcance al bloque, declaración, o la expresión en el que se utiliza. Esto es a diferencia de la var palabra clave, que define una variable global, o de forma local a una función entera independientemente de ámbito de bloque.
Variables declaradas por permitir tienen como alcance el bloque en el que se definen, así como en cualquier contenían sub-bloques. De esta manera, deja funciona muy parecido a var . La principal diferencia es que el alcance de un var variable es toda la función de cerramiento:
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 los programas y funciones, permitir , 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, dejar que alcance los límites de la variable a ese bloque. Tenga en cuenta la diferencia entre var cuyo alcance está dentro de la función en la que 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 se olvide que es característica ECMA6, así que no es totalmente compatible con todo, así que es mejor siempre transpiles a ECMA5 usando Babel, etc ... para obtener más información sobre la visita babel página web
Este es un ejemplo para añadir a lo que otros ya han escrito. Suponga que desea realizar una serie de funciones, adderFunctions
, donde cada función toma un solo argumento Número y devuelve la suma del argumento y el índice de la función de la matriz. Tratando de generar adderFunctions
con un bucle usando la palabra clave var
no va a 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 deseada de funciones 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 lugar de ello, 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 para nada: ahora tenemos una serie de funciones diferentes de 1000 en la memoria con exactamente el mismo comportamiento. Y si posteriormente que se actualice el valor de i
, la mutación afecta a todo el adderFunctions
.
Sin embargo, podemos intentarlo de nuevo usando 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 de 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 adderFunctions
se comporta como se esperaba.
Ahora, la imagen de mezclar los dos comportamientos y es probable que ver por qué no se recomienda mezclar el nuevo let
y const
con el var
de más edad en el mismo guión. Si lo hace, puede dar lugar a un cierto 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 deje que esto le suceda a usted. Utilice una desfibradora.
Nota: Este es un ejemplo de enseñanza destinado a demostrar el comportamiento
var
/let
en bucles y con cierres de función que también sería fácil de entender. Esta sería una forma terrible de añadir números. Pero la técnica general de la captura de datos en cierres de función anónimos podrían encontrar en el mundo real en otros contextos. Tu caso es distinto.
La diferencia está en el ámbito de la de las variables declaradas con cada uno.
En la práctica, hay una serie de consecuencias útiles de la diferencia en el ámbito de aplicación:
- variables de
let
sólo son visibles en su encierra más cercana bloque ({ ... }
). - variables de
let
sólo pueden utilizarse en líneas de código que se producen después se declara la variable (aunque que se izan !).
las variables -
let
no se pueden volver a declarar por unvar
olet
posterior. - las variables globales
let
no se agregan al objetowindow
global. - variables de
let
están fácil de usar con cierres (que no causan condiciones de carrera).
Las restricciones impuestas por let
reducir la visibilidad de las variables y aumentar la probabilidad de que las colisiones de nombres inesperadas serán encontrados temprano. Esto hace que sea más fácil hacer un seguimiento y razonar acerca de las variables, incluyendo su accesibilidad (ayudar con la recuperación de la memoria no utilizada) .
En consecuencia, las variables let
son menos propensos a causar problemas cuando se utilizan en grandes programas o cuando los marcos desarrollados independientemente se combinan en formas nuevas e inesperadas.
var
todavía puede ser útil si está seguro de que desea que el efecto cuando se utiliza un cierre en un bucle de unión individual (# 5) o para declarar variables globales externamente visibles en el código (# 4). El uso de var
para las exportaciones puede ser suplantado si export
migra fuera del espacio transpiler y en el núcleo del lenguaje.
Ejemplos
1. Ningún uso bloque que lo contiene exterior más cercana:
Este bloque de código arrojará un error de referencia debido a que el segundo uso de x
se produce fuera del bloque en el que 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 obras var
.
2. Sin el uso antes de la declaración:
Este bloque de código va a lanzar una ReferenceError
antes de que el código se puede ejecutar porque no se utiliza x
antes de que se declare:
{
x = x + 1; // ReferenceError during parsing: "x is not defined".
let x;
console.log(`x is ${x}`); // Never runs.
}
En contraste, el mismo ejemplo con análisis sintácticos var
y se ejecuta sin lanzar ninguna excepción.
3. Sin redeclaración:
El código siguiente muestra que una variable declarada con let
no puede declararse después:
let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared
4. Globales no unidos 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. uso fácil con cierres:
Las variables declaradas con var
no funcionan bien con cierres dentro de bucles. Aquí es un bucle simple que da salida a la secuencia de valores que el i
variable tiene en diferentes puntos en el tiempo:
for (let i = 0; i < 5; i++) {
console.log(`i is ${i}`), 125/*ms*/);
}
Específicamente, este Salidas:
i is 0
i is 1
i is 2
i is 3
i is 4
En JavaScript que a menudo utilizan las variables en un tiempo significativamente más tarde que cuando se crean. Cuando demostramos este 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, siempre y cuando nos quedamos con let
. Por el contrario, si hubiéramos usado var i
lugar:
for (var i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... el bucle da salida inesperada "i es 5" cinco veces:
i is 5
i is 5
i is 5
i is 5
i is 5
Que las dos funciones siguientes muestran 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
}
let
es interesante, ya que 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++);
}
}
}
})();
sólo cuenta [0, 1].
Función VS ámbito de bloque:
La principal diferencia entre var
y let
es que las variables declaradas con var
son Función de ámbito . Mientras que las funciones declaradas con let
son bloque de ámbito . 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 el testVar
primera función se llama a la variable foo, declarada con var
, sigue siendo accesible fuera del estado de if
. Esta variable de foo
estaría disponible todas partes en el ámbito de la testVar
Función: .
variables con let
:
Cuando el testLet
segunda función se llama a la barra variable declarada con let
, sólo es accesible dentro de la instrucción if
. Debido a que las variables declaradas con let
son bloque de ámbito (donde un bloque es el código entre corchetes por ejemplo if{}
, for{}
, function{}
).
variables de let
no consiguen izadas:
Otra diferencia entre var
y let
es variables con declarada con let
no se deje izada . Un ejemplo es la mejor manera de ilustrar este comportamiento:
variables con let
no get izadas:
console.log(letVar);
let letVar = 10;
// referenceError, the variable doesn't get hoisted
variables con var
hacer get izada:
console.log(varVar);
var varVar = 10;
// logs undefined, the variable gets hoisted
let
global no quede unido a window
:
Una variable declarada con let
en el ámbito global (que es el código que no está en una función) no se añaden como una propiedad del objeto window
global. Por ejemplo (esto es el código de 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 se debe utilizar sobre
let
var
?
Uso let
sobre var
cada vez que pueda, ya que es simplemente de ámbito más específico. Esto reduce los posibles conflictos de nombres que pueden ocurrir cuando se trata de un gran número de variables. var
se puede usar cuando se desea una variable global expresamente a ser en el objeto window
(siempre considerar cuidadosamente si esto es realmente necesario).
También parece que, al menos en Visual Studio 2015, mecanografiado 1.5, "var" permite que varias declaraciones del mismo nombre de variable en un bloque, y "dejar que" no lo hace.
Esto no generará un error de compilación:
var x = 1;
var x = 2;
Esta voluntad:
let x = 1;
let x = 2;
var
es ámbito global variable (polipasto-capaz).
let
y const
es bloquear el ámbito de aplicación.
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 se utiliza let
La palabra clave let
concede la variable declaración al alcance de cualquiera que sea el bloque (comúnmente un par { .. }
) está contenida en. En otras palabras, let
secuestra implícitamente alcance de cualquier bloque por su declaración de variables.
variables de let
no se puede acceder en el objeto window
porque no se puede acceder a nivel mundial.
function a(){
{ // this is the Max Scope for let variable
let x = 12;
}
console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined
cuando se utiliza var
var
y las variables en la ES5 tiene alcances en funciones que significan las variables son válidas dentro de la función y no fuera de la propia función.
variables de var
se puede acceder en el objeto window
porque no se puede acceder a nivel mundial.
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 más famosas preguntas de la entrevista en el ámbito de aplicación también puede ser suficiente el uso exacto de let
y var
de la siguiente manera;
Al utilizar 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 cuando se utiliza let
, para cada iteración del bucle la variable está en el ámbito y tiene su propia copia.
Al utilizar 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 cuando se utiliza var
, para cada iteración del bucle la variable está en el ámbito y ha compartido copia.
Si leo las especificaciones en ese momento let
afortunadamente también se puede aprovechar para evitar funciones de auto invocación utilizan para simular sólo los miembros privados - un patrón de diseño popular que disminuye la legibilidad del código, complica la depuración, que no añade reales protección de código u otro beneficio - excepto tal vez satisfacer el deseo de alguien por la semántica, por lo que dejar de usarlo. / Diatriba
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
Vea ' Emulando interfaces privadas '
Algunos cortes 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"
get y set 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)
dejar vs var. Es todo acerca de alcance .
var las variables son globales y se puede acceder básicamente en todas partes, mientras que dejar que las variables no son globales y sólo existen hasta que un paréntesis de cierre los mata.
Vea mi ejemplo a continuación, y observar cómo el león (LET) variable actúa de manera diferente en los dos console.logs; se hace fuera de campo en la segunda console.log.
var cat = "cat";
let dog = "dog";
var animals = () => {
var giraffe = "giraffe";
let lion = "lion";
console.log(cat); //will print 'cat'.
console.log(dog); //will print 'dog', because dog was declared outside this function (like var cat).
console.log(giraffe); //will print 'giraffe'.
console.log(lion); //will print 'lion', as lion is within scope.
}
console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.
let es una parte de ES6. Estas funciones le explicará 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
}
Anteriormente sólo había dos ámbitos en JavaScript, es decir, funcionales y globales. Con la palabra clave 'let
' JavaScript ha introducido las variables block-level
.
Para tener una comprensión completa de la palabra clave 'dejar', ES6: ‘deje’ palabra clave para declarar variables en JavaScript ayudará
. Ahora creo que hay una mejor definición del alcance de las variables de un bloque de instrucciones usando 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 va a empezar a utilizar aquí después de dejar por lo que tendrán alcance similar en JavaScript como otros lenguajes, Java, C #, etc.
Las personas con no una clara comprensión acerca de la determinación del alcance de JavaScript utilizados para cometer el error anterior.
Elevadores no se admite el uso de let
.
Con este enfoque errores presentes en JavaScript están siendo eliminados.
Consulte ES6 En Profundidad :. const y dejar que para entenderlo mejor
En este artículo se define claramente la diferencia entre var, y mucho 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 reasignado, tal como una mostrador en un bucle, o un intercambio de valor en un algoritmo. Se señala también que la variable será utilizada únicamente en el bloque se define en, que no siempre es la función entera que contiene.
var
ahora es la señal más débil disponible cuando se define una variable en JavaScript. La variable puede o no puede ser reasignado, y el variable puede o no puede ser utilizado para una función entera, o simplemente para El propósito de un bloque o de bucle.
https: // medio. com / javascript escena / javascript-ES6-var-let-o-const-ba58b8dcde75 # .esmkpbg9b
Como se mencionó anteriormente:
La diferencia es la determinación del alcance.
var
está en el ámbito de la función más cercana bloque ylet
está en el ámbito de la más cercano bloque que lo contiene , que puede ser menor que un bloque de función. Ambos son global si fuera de cualquier block.Lets ver un ejemplo:
Ejemplo 1:
En mis dos ejemplos Tengo un myfunc
función. myfunc
contiene una myvar
variable es igual a 10.
En mi primer ejemplo puedo comprobar si myvar
es igual a 10 (myvar==10
). Si es así, me declaro un AGIAN myvar
variable (ahora tengo dos variables MYVAR) utilizando la palabra clave var
y asignarle un nuevo valor (20). En la siguiente línea imprimo su valor en mi consola. Después de que el bloque condicional vuelvo a imprimir el valor de myvar
en mi consola. Si nos fijamos en la salida del myfunc
, myvar
tiene valor es igual a 20.
Ejemplo 2:
En mi segundo ejemplo en lugar de utilizar la palabra clave var
en mi bloque condicional Declaro myvar
usando la palabra clave let
. Ahora cuando llamo myfunc
consigo dos salidas diferentes: myvar=20
y myvar=10
Así que la diferencia es muy simple es decir su alcance.
Tome un vistazo a esta imagen, he creado un ejemplo muy simple para la demostración de las variables const
y let
. Como se puede ver, cuando intenta cambiar la variable const
, obtendrá el error ( El intento de anular 'nombre' que es constante '), pero echar un vistazo a la variable let
...
En primer lugar, declaramos let age = 33
, y posteriormente asignamos alguna otra age = 34;
valor, que está bien, no tenemos ningún error cuando tratamos de cambiar let
variables
Creo que los términos y la mayoría de los ejemplos son un poco abrumador,
El principal problema que tuve personalmente con la diferencia es la comprensión de lo que es un "bloque" es.
En algún momento me di cuenta, un bloque sería ningún llaves a excepción de la declaración IF
.
un {
corchete de apertura de una función o bucle definirá un nuevo bloque, nada definido con let
dentro de ella, no estará disponible después de la }
corchete de cierre de la misma cosa (función o bucle);
Con esto en mente, era más fácil de entender:
let msg = "Hello World";
function doWork() { // msg will be available since it was defined above this opening bracket!
let friends = 0;
console.log(msg);
// with VAR though:
for (var iCount2 = 0; iCount2 < 5; iCount2++) {} // iCount2 will be available after this closing bracket!
console.log(iCount2);
for (let iCount1 = 0; iCount1 < 5; iCount1++) {} // iCount1 will not be available behind this closing bracket, it will return undefined
console.log(iCount1);
} // friends will no be available after this closing bracket!
doWork();
console.log(friends);
Ahora que estoy tratando de obtener una comprensión más profunda de JavaScript voy a compartir mi breve investigación que contiene algunas de las grandes piezas ya discutidos más algunos otros detalles en una perspectiva diferente.
La comprensión de la diferencia entre var y permitir puede ser más fácil si entendemos la diferencia entre función y Ámbito de un bloque .
Vamos a considerar los siguientes casos:
(function timer() {
for(var i = 0; i <= 5; i++) {
setTimeout(function notime() { console.log(i); }, i * 1000);
}
})();
Stack VariableEnvironment //one VariablEnvironment for timer();
// when the timer is out - the value will be the same value for each call
5. [setTimeout, i] [i=5]
4. [setTimeout, i]
3. [setTimeout, i]
2. [setTimeout, i]
1. [setTimeout, i]
0. [setTimeout, i]
####################
(function timer() {
for (let i = 0; i <= 5; i++) {
setTimeout(function notime() { console.log(i); }, i * 1000);
}
})();
Stack LexicalEnvironment - each iteration has a new lexical environment
5. [setTimeout, i] [i=5]
LexicalEnvironment
4. [setTimeout, i] [i=4]
LexicalEnvironment
3. [setTimeout, i] [i=3]
LexicalEnvironment
2. [setTimeout, i] [i=2]
LexicalEnvironment
1. [setTimeout, i] [i=1]
LexicalEnvironment
0. [setTimeout, i] [i=0]
cuando timer()
se llama un ExecutionContext se crea que contendrá tanto el VariableEnvironment y todo el LexicalEnvironments correspondiente a cada iteración.
Y un ejemplo más simple
Función Alcance
function test() {
for(var z = 0; z < 69; z++) {
//todo
}
//z is visible outside the loop
}
Ámbito de un bloque
function test() {
for(let z = 0; z < 69; z++) {
//todo
}
//z is not defined :(
}
Quiero vincular estas palabras clave para el contexto de ejecución, debido a que el contexto de ejecución es importante en todo esto. El contexto de ejecución tiene dos fases: una fase de creación y la fase de ejecución. Además, cada contexto de ejecución tiene un entorno de Medio Ambiente y Outer Variable (su entorno léxico).
Durante la fase de creación de un contexto de ejecución, var, const dejó y todavía almacenará su variable en la memoria con un valor indefinido en la variable de entorno del contexto de ejecución dada. La diferencia está en la fase de ejecución. Si utiliza una variable de referencia definida con var antes de que se le asigna un valor, sólo será indefinido. será elevado no es una excepción.
Sin embargo, no se puede hacer referencia a la variable declarada con let o const hasta que se declara. Si intenta utilizar antes de que se declara, a continuación, una excepción se planteó durante la fase de ejecución del contexto de ejecución. Ahora la variable seguirá estando en la memoria, por cortesía de la fase de creación del contexto de ejecución, pero el motor no permitirá que lo uses:
function a(){
b;
let b;
}
a();
> Uncaught ReferenceError: b is not defined
Con una variable definida con var, si el motor no puede encontrar la variable en la variable de entorno del contexto de ejecución actual, entonces se va a subir la cadena de ámbito (el entorno exterior) y comprobar la variable de entorno del ambiente externo para la variable. Si no se puede encontrar allí, continuará buscando en la cadena de ámbitos. Este no es el caso con let y const.
La segunda característica de let es que introduce ámbito de bloque. Los bloques se definen por llaves. Los ejemplos incluyen bloques de función, si los bloques, de bloques, etc. Cuando se declara una variable con let en el interior de un bloque, la variable sólo está disponible en el interior del bloque. De hecho, cada vez que el bloque es ejecutado, tal como dentro de un bucle, se creará una nueva variable en la memoria.
ES6 también introduce la palabra clave const para declarar variables. const también está bloque de ámbito. La diferencia entre let y const es que las variables const necesitan ser declarados utilizando un inicializador, o se generará un error.
Y, por último, cuando se trata del contexto de ejecución, las variables definidas con var se unen a la 'presente' objeto. En el contexto de ejecución global, que será el objeto de la ventana en los navegadores. Este no es el caso, para alquiler o const.