Pregunta

la declaración let .

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?

¿Fue útil?

Solución

reglas

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:

 mesa de soporte


¿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 a var. La principal diferencia es que el alcance de una variable var 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() .

Se requiere

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):
introducir descripción de la imagen aquí

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 no

    let 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 y let 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 variable hugeData en absoluto. En teoría, después de carreras process(..), la enorme estructura de datos hugeData 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ón click 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 con let

    // 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:

  1. variables de let sólo son visibles en su encierra más cercana bloque ({ ... }).
  2. 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 !).
  3. las variables
  4. let no se pueden volver a declarar por un var o let posterior.
  5. las variables globales let no se agregan al objeto window global.
  6. 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 y let 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.

dejar que la palabra clave

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.

introducir descripción de la imagen aquí

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top