w3schools - var en javascript




¿Cuál es la diferencia entre usar "let" y "var" para declarar una variable en JavaScript? (18)

ECMAScript 6 introdujo la declaración let . He oído que se describe como una variable "local", pero aún no estoy seguro de cómo se comporta de manera diferente a la palabra clave var .

¿Cuáles son las diferencias? ¿Cuándo debe let usar sobre var ?


let

Alcance del bloque

Las variables declaradas con la palabra clave let tienen un ámbito de bloque, lo que significa que están disponibles solo en el bloque en el que se declararon.

En el nivel superior (fuera de una función)

En el nivel superior, las variables declaradas utilizando no let crear propiedades en el objeto global.

var globalVariable = 42;
let blockScopedVariable = 43;

console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43

console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined

Dentro de una funcion

Dentro de una función (pero fuera de un bloque), tenga el mismo alcance que var .

(() => {
  var functionScopedVariable = 42;
  let blockScopedVariable = 43;

  console.log(functionScopedVariable); // 42
  console.log(blockScopedVariable); // 43
})();

console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

Dentro de un bloque

Las variables declaradas usando let dentro de un bloque no se pueden acceder fuera de ese bloque.

{
  var globalVariable = 42;
  let blockScopedVariable = 43;
  console.log(globalVariable); // 42
  console.log(blockScopedVariable); // 43
}

console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

Dentro de un bucle

Las variables declaradas con bucles de entrada pueden ser referenciadas solo dentro de ese bucle.

for (var i = 0; i < 3; i++) {
  var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4

for (let k = 0; k < 3; k++) {
  let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.

Bucles con cierres

Si utiliza let lugar de var en un bucle, con cada iteración obtendrá una nueva variable. Eso significa que puede usar un cierre de forma segura dentro de un bucle.

// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}

Zona muerta temporal

Debido a la zona muerta temporal , no se puede acceder a las variables declaradas utilizando let antes de declararlas. Intentar hacerlo arroja un error.

console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;

No re-declarar

No puedes declarar la misma variable varias veces usando let . Tampoco puede declarar una variable usando let con el mismo identificador que otra variable que fue declarada usando var .

var a;
var a; // Works fine.

let b;
let b; // SyntaxError: Identifier 'b' has already been declared

var c;
let c; // SyntaxError: Identifier 'c' has already been declared

const

const es bastante similar a let que let de ámbito de bloques y tiene TDZ. Hay, sin embargo, dos cosas que son diferentes.

Sin reasignación

La variable declarada usando const no puede ser reasignada.

const a = 42;
a = 43; // TypeError: Assignment to constant variable.

Tenga en cuenta que no significa que el valor sea inmutable. Sus propiedades todavía se pueden cambiar.

const obj = {};
obj.a = 42;
console.log(obj.a); // 42

Si desea tener un objeto inmutable, debe usar Object.freeze() .

Se requiere inicializador

Siempre debe especificar un valor al declarar una variable usando const .

const a; // SyntaxError: Missing initializer in const declaration

Función VS ámbito de bloque:

La principal diferencia entre 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)


A la respuesta aceptada le falta un punto:

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined

Aquí hay un ejemplo de la diferencia entre los dos (el soporte acaba de comenzar para Chrome):

Como puede ver, la variable var j sigue teniendo un valor fuera del alcance del bucle for (Ámbito del bloque), pero la variable let i no está definida fuera del alcance del bucle for.

"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
  console.log(j);
}

console.log(j);

console.log("let:");
for (let i = 0; i < 2; i++) {
  console.log(i);
}

console.log(i);


Aquí hay una explicación de la palabra clave let con algunos ejemplos.

Dejamos los trabajos muy parecidos a var. La principal diferencia es que el alcance de una variable var es la función de cierre completa.

Esta tabla en Wikipedia muestra qué navegadores son compatibles con Javascript 1.7.

Tenga en cuenta que solo los navegadores Mozilla y Chrome lo admiten. IE, Safari, y potencialmente otros no.


Hay algunas diferencias sutiles: let alcance se comporte más como el alcance variable en más o menos otros idiomas.

Por ejemplo, se dirige al bloque adjunto, no existen antes de que se declaren, etc.

Sin embargo, vale la pena señalar que let solo una parte de las nuevas implementaciones de Javascript y que tiene diversos grados de compatibilidad con el navegador .


La 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



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

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


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.


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


También parece que, al menos en Visual Studio 2015, TypeScript 1.5, "var" permite múltiples declaraciones del mismo nombre de variable en un bloque, y "let" no.

Esto no generará un error de compilación:

var x = 1;
var x = 2;

Esta voluntad:

let x = 1;
let x = 2;

Ahora creo que hay un mejor alcance de las variables a un bloque de declaraciones utilizando let:

function printnums()
{
    // i is not accessible here
    for(let i = 0; i <10; i+=)
    {
       console.log(i);
    }
    // i is not accessible here

    // j is accessible here
    for(var j = 0; j <10; j++)
    {
       console.log(j);
    }
    // j is accessible here
}

Creo que la gente comenzará a usar Let here after para que tengan un alcance similar en JavaScript como otros lenguajes, Java, C #, etc.

Las personas que no tienen una comprensión clara sobre el alcance en JavaScript solían cometer el error antes.

No se soporta el izamiento utilizando let.

Con este enfoque se eliminan los errores presentes en JavaScript.

Refiérase a ES6 en profundidad: deje que consten para entenderlo mejor.



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

Revisa este enlace en MDN

let x = 1;

if (x === 1) {
let x = 2;

console.log(x);
// expected output: 2
}

console.log(x);
// expected output: 1

Si leo las especificaciones correctamente, let afortunadamente también se puede aprovechar para evitar las funciones de auto-invocación usadas para simular miembros exclusivos privados, un patrón de diseño popular que reduce la legibilidad del código, complica la depuración, que no agrega protección de código real ni otro beneficio Deseo de semántica, así que deja de usarlo. /despotricar

var SomeConstructor;

{
    let privateScope = {};

    SomeConstructor = function SomeConstructor () {
        this.someProperty = "foo";
        privateScope.hiddenProperty = "bar";
    }

    SomeConstructor.prototype.showPublic = function () {
        console.log(this.someProperty); // foo
    }

    SomeConstructor.prototype.showPrivate = function () {
        console.log(privateScope.hiddenProperty); // bar
    }

}

var myInstance = new SomeConstructor();

myInstance.showPublic();
myInstance.showPrivate();

console.log(privateScope.hiddenProperty); // error

Consulte ' Emulación de interfaces privadas '.





let