scope que - ¿Cuál es la diferencia entre usar "let" y "var" para declarar una variable en JavaScript?




cuando cual (23)

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.

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 ?


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.

varAhora 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


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.


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
}

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


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 '.




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].


Función VS ámbito de bloque:

La principal diferencia entre vary letes que las variables declaradas varson función de ámbito . Mientras que las funciones declaradas letson 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 testVarse llama a la primera función, la variable foo, declarada con var, sigue siendo accesible fuera de la ifdeclaración. Esta variable fooestaría disponible en cualquier parte dentro del alcance de la testVar función .

variables con let:

Cuando testLetse llama a la segunda función, la barra de variables, declarada con let, solo es accesible dentro de la ifdeclaración. Debido a que las variables declaradas con letson 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 vary letcon 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 letno se apega a window:

Una variable declarada con leten el ámbito global (que es un código que no está en una función) no se agrega como una propiedad en el windowobjeto 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 letser usado más var?

Utilizar letmás varcada 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. varse puede usar cuando desea que una variable global esté explícitamente en el windowobjeto (siempre considere cuidadosamente si esto es realmente necesario)


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 .


var Es una variable de alcance global (elevable).

lety constes á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


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

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.

DEMO

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) })
}

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:

  1. letlas variables solo son visibles en su bloque de cierre más cercano ( { ... }).
  2. letlas 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 !)
  3. letLas variables no pueden ser redeclaradas por un posterior varo let.
  4. Las letvariables globales no se agregan al windowobjeto global .
  5. letLas variables son fáciles de usar con cierres (no causan condiciones de carrera ).

Las restricciones impuestas letreducen 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, letes 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.

varaú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 varfor export puede ser suplantado si exportmigra 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 xproduce 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 varobras.

2. Sin uso antes de la declaración:
este bloque de código lanzará un ReferenceErrorcódigo antes de que se pueda ejecutar el código porque xse 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 varanaliza y ejecuta sin lanzar excepciones.

3. No redeclaración: el siguiente código demuestra que una variable declarada con letno 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 varno funcionan bien con cierres dentro de los bucles. Aquí hay un bucle simple que genera la secuencia de valores que la variable itiene 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 ilugar:

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

Como se ha mencionado más arriba:

La diferencia es el alcance. vartiene el alcance del bloque de función más cercano y el letalcance 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. myfunccontiene una variable myvarigual a 10. En mi primer ejemplo, compruebo si myvares igual a 10 ( myvar==10). En caso afirmativo, nuevamente declaro una variable myvar(ahora tengo dos variables myvar) usando varpalabras 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 myvaren mi consola. Si nos fijamos en la salida de myfunc, myvartiene valor igual a 20.

Ejemplo 2: en mi segundo ejemplo, en lugar de usar varpalabras clave en mi bloque condicional, declaro myvarusar letpalabras clave. Ahora cuando llamo myfuncme sale dos salidas diferentes: myvar=20y myvar=10.

Así que la diferencia es muy simple, es decir, su alcance.


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)

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.


  • Variable No Levantamiento

    no 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 y let 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 variable hugeData en absoluto. Teóricamente, después de que process(..) ejecuta el process(..) , la enorme estructura de datos hugeData 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 de click 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 bucles

    let 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 con let

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


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

¿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.


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);


Este es muy simple.

if(data) {
  //Comes inside only if the data is not empty and not null 
}




javascript scope ecmascript-6 var let