javascript - entre - hoisting
¿Las variables declaradas con let o const no se izan en ES6? (4)
@thefourtheye tiene razón al decir que no se puede acceder a estas variables antes de declararlas. Sin embargo, es un poco más complicado que eso.
¿Las variables declaradas con
let
oconst
no están elevadas? ¿Qué está pasando aquí realmente?
Todas las declaraciones
(
var
,
let
,
const
,
function
,
function*
,
class
)
se "izan"
en JavaScript.
Esto significa que si un nombre se declara en un ámbito, en ese ámbito el identificador siempre hará referencia a esa variable en particular:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Esto es cierto tanto para la función como para los ámbitos de bloque 1 .
La diferencia entre las declaraciones
var
/
function
/
function*
y
let
/
const
/
class
es la
inicialización
.
Los primeros se inicializan con
undefined
o la función (generador) justo cuando se crea el enlace en la parte superior del alcance.
Sin embargo, las variables declaradas léxicamente permanecen sin
inicializar
.
Esto significa que se produce una excepción
ReferenceError
cuando intenta acceder a ella.
Solo se inicializará cuando se evalúe la declaración
let
/
const
/
class
, todo antes (arriba) que se llama
zona muerta temporal
.
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Tenga en cuenta que a
let y;
La instrucción inicializa la variable con
undefined
como
let y = undefined;
tendría.
La zona muerta temporal no es una ubicación sintáctica, sino el tiempo entre la creación de la variable (alcance) y la inicialización. No es un error hacer referencia a la variable en el código encima de la declaración siempre que ese código no se ejecute (por ejemplo, un cuerpo de función o simplemente un código muerto), y arrojará una excepción si accede a la variable antes de la inicialización, incluso si el acceso el código está debajo de la declaración (por ejemplo, en una declaración de función izada que se llama demasiado pronto).
¿Hay alguna diferencia entre
let
yconst
en este asunto?
No, funcionan igual en lo que respecta a la elevación.
La única diferencia entre ellos es que una
const
debe ser y solo puede asignarse en la parte inicializadora de la declaración (
const one = 1;
ambas
const one;
y las reasignaciones posteriores como
one = 2
no son válidas).
1: las declaraciones
var
todavía funcionan solo en el nivel de función, por supuesto
He estado jugando con ES6 durante un tiempo y noté que mientras las variables declaradas con
var
se izan como se esperaba ...
console.log(typeof name); // undefined
var name = "John";
... las variables declaradas con
let
o
const
parecen tener algunos problemas con la elevación:
console.log(typeof name); // ReferenceError
let name = "John";
y
console.log(typeof name); // ReferenceError
const name = "John";
¿Significa esto que las variables declaradas con
let
o
const
no se izan?
¿Qué está pasando aquí realmente?
¿Hay alguna diferencia entre
let
y
const
en este asunto?
Citando las especificaciones de ECMAScript 6 (ECMAScript 2015), la sección de
declaraciones
let
y
const
,
Las variables se crean cuando se crea una instancia de su entorno léxico que contiene, pero no se puede acceder de ninguna manera hasta que se evalúe el enlace léxico de la variable .
Entonces, para responder a su pregunta, sí,
let
y conteste pero no puede acceder a ellos antes de que se evalúe la declaración real en tiempo de ejecución.
En ECMAScript 2015,
let
y
const
se izan pero no se inicializan.
Hacer referencia a la variable en el bloque antes de la declaración de la variable da como resultado un
ReferenceError
porque la variable está en una "zona muerta temporal" desde el inicio del bloque hasta que se procese la declaración.
console.log(x); // ReferenceError
let x = 3;
ES6
presenta las variables
Let
que aparecen con el
block level scoping
.
Hasta
ES5
no teníamos el
block level scoping
, por lo que las variables que se declaran dentro de un bloque siempre se
hoisted
para el alcance del nivel de función.
Básicamente,
Scope
refiere a dónde están visibles las variables en su programa, lo que determina dónde se le permite usar las variables que ha declarado.
En
ES5
tenemos
global scope,function scope and try/catch scope
, con
ES6
también obtenemos el alcance del nivel de bloque usando Let.
-
Cuando define una variable con la palabra clave
var
, se conoce toda la función desde el momento en que se define. -
Cuando define una variable con una declaración
let
, solo se conoce en el bloque que está definido.function doSomething(arr){ //i is known here but undefined //j is not known here console.log(i); console.log(j); for(var i=0; i<arr.length; i++){ //i is known here } //i is known here //j is not known here console.log(i); console.log(j); for(let j=0; j<arr.length; j++){ //j is known here } //i is known here //j is not known here console.log(i); console.log(j); } doSomething(["Thalaivar", "Vinoth", "Kabali", "Dinesh"]);
Si ejecuta el código, podría ver que la variable
j
solo se conoce en el
loop
y no antes y después.
Sin embargo, nuestra variable
i
es conocida en
entire function
desde el momento en que se define en adelante.
Hay otra gran ventaja con let, ya que crea un nuevo entorno léxico y también une un valor fresco en lugar de mantener una referencia antigua.
for(var i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
for(let i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
El primer bucle
for
siempre imprime el
último
valor, con
let
crea un nuevo ámbito y enlaza valores nuevos imprimiéndonos
1, 2, 3, 4, 5
.
Llegando a
constants
, funciona básicamente como
let
, la única diferencia es que su valor no se puede cambiar.
En constantes, la
mutación está permitida pero la reasignación no está permitida.
const foo = {};
foo.bar = 42;
console.log(foo.bar); //works
const name = []
name.push("Vinoth");
console.log(name); //works
const age = 100;
age = 20; //Throws Uncaught TypeError: Assignment to constant variable.
console.log(age);
Si una constante se refiere a un
object
, siempre se referirá al
object
pero el
object
sí se puede cambiar (si es mutable).
Si desea tener un
object
inmutable, puede usar
Object.freeze([])