¿Las variables declaradas con let o const no se elevan en ES6?
He estado jugando con ES6 durante un tiempo y me di cuenta de que las variables while declaradas con var
se elevan como se esperaba...
console.log(typeof name); // undefined
var name = "John";
...las variables declaradas con let
o const
parecen tener algunos problemas con el levantamiento:
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 realmente aquí? Hay alguna diferencia entre let
y const
en este asunto?
3 answers
@thefourtheye tiene razón al decir que estas variables no se puede acceder antes de que se declaren. Sin embargo, es un poco más complicado que eso.
¿Las variables declaradas con
let
oconst
no están izadas? ¿Qué está pasando realmente aquí?
Todas las declaraciones (var
, let
, const
, function
, function*
, class
) son "izada" en JavaScript. Esto significa que si se declara un nombre en un ámbito, en ese ámbito el identificador siempre haga referencia a esa variable 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 ámbitos de función como de bloque1.
La diferencia entre var
/function
/function*
declaraciones y let
/const
/class
declaraciones es el inicialización.
Los primeros se inicializan con undefined
o la función (generator) justo cuando se crea el enlace en la parte superior del ámbito. Sin embargo, las variables declaradas léxicamente permanecen no inicializadas. Esto significa que un ReferenceError
la excepción se lanza cuando intenta acceder a ella. Solo se inicializará cuando el let
/const
/class
se evalúa la declaración, todo lo anterior (arriba) que se llama la zona muerta temporal .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Observe que una instrucción let y;
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 (ámbito) y la inicialización. No es un error para hacer referencia a la variable en el código por encima de la declaración siempre y cuando ese código no se ejecute (por ejemplo, un cuerpo de función o simplemente código muerto), y lanzará una excepción si accede a la variable antes de la inicialización, incluso si el código de acceso está debajo de la declaración (por ejemplo, en una declaración de función elevada 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 considerar. La única diferencia entre ellos es que una const
ant debe ser y solo puede ser asignada en la parte inicializadora de la declaración (const one = 1;
, tanto const one;
como reasignaciones posteriores como one = 2
no son válidas).
1: var
las declaraciones siguen funcionando solo en el nivel de función, por supuesto
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 14:28:42
Citando la especificación ECMAScript 6 (ECMAScript 2015) , let
y const
declaraciones sección,
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 la vinculación LexicalBinding de la variable.
Entonces, para responder a su pregunta, sí, let
y const
hoist pero no puede acceder a ellos antes de que la declaración real se evalúe en tiempo de ejecución.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 14:50:57
ES6
introduce Let
variables que viene con block level scoping
. Hasta ES5
no teníamos block level scoping
, por lo que las variables que se declaran dentro de un bloque son siempre hoisted
a nivel de función de alcance.
Básicamente Scope
se refiere a dónde en su programa son visibles sus variables, 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 se define una variable con la palabra clave
var
, se conoce toda la función desde el momento en que se define. -
Cuando se define una variable con la instrucción
let
solo se conoce en el bloque que se define.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 loop
y no antes y después. Sin embargo, nuestra variable i
se conoce en el entire function
desde el momento en que se define en adelante.
Hay otra gran ventaja usando let ya que crea un nuevo entorno léxico y también une 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 frescos 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 se permite la mutación, pero no se permite la reasignación.
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 una object
, siempre se referirá al object
pero el object
en sí puede ser cambiado (si es mutable). Si te gusta tener un object
inmutable, puedes usar Object.freeze([])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 06:46:36