Expresión let en JavaScript

Expresión let en JavaScript
Expresión let en JavaScript

Una expresión let en javascript declara una variable local para la partición del bloque, cuyo valor inicial se puede inicializar opcionalmente.

Características generales

Una expresión let en javascript permite declarar variables cuyo alcance se limita a la declaración del bloque, o a la expresión en la que se utilizó. Contrasta con una palabra reservada var que define una variable que es global o local para la función de estado independientemente del alcance del bloque.

Estructura let en javascript

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];

varnameN

El nombre de la variable, que puede ser cualquier identificador JavaScript válido.

valueN

Se puede utilizar el valor inicial de la variable y cualquier expresión válida en JavaScript.

Reglas de dominio

Las variables let declaradas en javascript a través de su dominio serán la sección del bloque en la que se definen, así como las subsecciones que contenga. Esto significa que las variables declaradas vía let son muy similares a var. Pero la principal diferencia entre ellos es que el dominio de las variables var será la función completa que contienen:

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;    // la variable en sí es
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // una diferente
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

Funciones internas

Las variables let definidas a través de funciones internas permiten una generación de código más explícita:

var list = document.getElementById('list');

for (let i = 1; i <= 5; i++) {
  let item = document.createElement('li');
  item.appendChild(document.createTextNode('Item ' + i));

  item.onclick = function(ev) {
    console.log('Item ' + i + ' is clicked.');
  };
  list.appendChild(item);
}
// Para crear el mismo efecto pero usando var 
// tenemos que crear un contexto diferente 
// usando una expresión cerrada para mantener el cierre del valor 

for (var i = 1; i <= 5; i++) {
  var item = document.createElement('li');
  item.appendChild(document.createTextNode('Item ' + i));

  (function(i){
    item.onclick = function(ev) {
      console.log('Item ' + i + ' is clicked.');
    };
  })(i);
  list.appendChild(item);
}

El ejemplo anterior funcionó como debería porque las cinco copias de la función interna anónima se refieren a cinco copias diferentes de la variable i. Tenga en cuenta que el ejemplo anterior no funcionará si colocamos var en lugar de let porque todas las funciones internas devolverán el último valor de la variable i cual es 6. Hay que tener en cuenta que mantuvimos claro el alcance alrededor del ciclo de iteración moviendo todo el código que crea los nuevos elementos al alcance de cada iteración. Tenga en cuenta que let (a diferencia de var) en javascript no creará una propiedad en el objeto global, por ejemplo:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

Simulación de variables especiales

Cuando se trata de funciones de constructor, es posible usar let para compartir uno o más elementos sin usar cierres:

var Thing;

{
  let privateScope = new WeakMap();
  let counter = 0;

  Thing = function() {
    this.someProperty = 'foo';
    
    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function() {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function() {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

var thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

Errores con let

Volver a declarar la misma variable dentro de la misma función o sección resultará en SyntaxError:

if (x) {
  let foo;
  let foo; // SyntaxError
}

En ECMAScript 2015, las declaraciones sobre variables let no pasarán por el contexto de ejecución actual, y hacer referencia a las variables en la partición del bloque antes de que se inicializan provocará una ocurrencia ReferenceError(a diferencia de las variables declaradas mediante var, que tendrán el valor undefined). Es decir, la variable estará en una «zona muerta temporal» desde el inicio de la sección del bloque hasta que se inicialice la variable.

function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2;
}

Puede encontrar errores en las expresiones switch porque constituyen una sección de un solo bloque:

let x = 1;
switch(x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo;   // SyntaxError debido a una nueva declaración de 
    break;
}

Pero es importante tener en cuenta que las particiones de bloque que están anidadas dentro de una partición case crearán un nuevo campo de bloque y no habrá errores relacionados con la re-declaración de variables aquí:

let x = 1;

switch(x) {
  case 0: {
    let foo;
    break;
  }  
  case 1: {
    let foo;
    break;
  }
}

Campos masivos

Cuando la palabra reservada let se usa dentro de un bloque, el dominio de la variable se limita a ese bloque. Note las diferencias entre esta y aquella var cuyo dominio es la función completa en la que está definida:

var a = 4;
var b = 6;

if (a === 4) {
  var a = 14;   // dominio público 
  let b = 18;  // el dominio está solo dentro de la expresión condicional

 console.log(a);  // 14
 console.log(b);  // 18
} 

console.log(a); // 14
console.log(b); // 2

Soporte de navegadores

CaracterísticaChromeFirefoxIEOperaSafari
Soporte básico4144111710