@thefourtheye está correto ao dizer que essas variáveis não podem ser acessadas antes de serem declaradas. No entanto, é um pouco mais complicado que isso.
As variáveis são declaradas com let
ou const
não içadas? O que realmente está acontecendo aqui?
Todas as declarações ( var
, let
, const
, function
, function*
, class
) são "içada" em JavaScript. Isso significa que se um nome for declarado em um escopo, nesse escopo, o identificador sempre fará referência a essa variável específica:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Isso vale para os escopos de função e bloco 1 .
A diferença entre var
/ function
/ function*
declarações e let
/ const
/ class
declarações é a inicialização .
Os primeiros são inicializados com undefined
ou a função (gerador) logo que a ligação é criada na parte superior do escopo. As variáveis declaradas lexicamente, no entanto, não são inicializadas . Isso significa que uma ReferenceError
exceção é lançada quando você tenta acessá-la. Ele só será inicializado quando a instrução let
/ const
/ class
for avaliada, tudo antes (acima) que é chamado de zona morta temporal .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Observe que uma let y;
instrução inicializa a variável com undefined
like let y = undefined;
.
A zona morta temporal não é um local sintático, mas o tempo entre a criação da variável (escopo) e a inicialização. Não é um erro referenciar a variável no código acima da declaração, desde que esse código não seja executado (por exemplo, um corpo de função ou simplesmente código morto), e será lançada uma exceção se você acessar a variável antes da inicialização, mesmo que o acesso código está abaixo da declaração (por exemplo, em uma declaração de função içada que é chamada muito cedo).
Existe alguma diferença entre let
e const
neste assunto?
Não, eles funcionam da mesma forma que o içamento é considerado. A única diferença entre eles é que uma const
formiga deve ser e só pode ser atribuída na parte inicializadora da declaração ( const one = 1;
tanto as const one;
reatribuições quanto as posteriores one = 2
são inválidas).
1: as var
declarações ainda estão funcionando apenas no nível da função, é claro
let foo = () => bar; let bar = 'bar'; foo();
ilustra todas as declarações são içadas efeito ainda melhor, porque não é óbvio devido à zona morta temporal.const
mesmolet
é uma falha de design. Dentro de um escopo,const
deveria ter sido feito para ser içado e inicializado just-in-time quando é acessado. Realmente, eles devem ter umaconst
, alet
e outra palavra-chave que crie uma variável que funcione como um "somente leitura"let
.Citando a seção de especificações
let
econst
declarações do ECMAScript 6 (ECMAScript 2015) ,Portanto, para responder sua pergunta, sim,
let
econst
içar, mas você não pode acessá-las antes que a declaração real seja avaliada em tempo de execução.fonte
ES6
apresentaLet
variáveis que surgemblock level scoping
. AtéES5
que não tivéssemosblock level scoping
, as variáveis declaradas dentro de um bloco semprehoisted
devem funcionar com escopo no nível.Scope
Refere-se basicamente a onde no seu programa suas variáveis estão visíveis, o que determina onde você tem permissão para usar as variáveis declaradas. EmES5
temosglobal scope,function scope and try/catch scope
, comES6
nós também obter o escopo de nível de bloco usando Let.var
palavra - chave, é conhecida toda a função a partir do momento em que é definida.Quando você define uma variável com
let
instrução, ela é conhecida apenas no bloco em que está definida.Se você executar o código, poderá ver que a variável
j
é conhecida apenas noloop
e não antes e depois. No entanto, nossa variáveli
é conhecida noentire function
momento em que é definida em diante.Há outra grande vantagem do uso do let, pois ele cria um novo ambiente lexical e também agrega novo valor ao invés de manter uma referência antiga.
O primeiro
for
loop sempre imprime o último valor, comlet
ele cria um novo escopo e vincula novos valores nos imprimindo1, 2, 3, 4, 5
.Vindo para
constants
, funciona basicamente comolet
, a única diferença é que o valor deles não pode ser alterado. Em constantes, a mutação é permitida, mas a reatribuição não é permitida.Se uma constante se referir a um
object
, sempre se referirá aoobject
mas oobject
próprio pode ser alterado (se for mutável). Se você gosta de ter um imutávelobject
, você pode usarObject.freeze([])
fonte
Dos documentos da Web MDN:
No ECMAScript 2015,
let
econst
são içados, mas não inicializados. A referência à variável no bloco antes da declaração da variável resulta emReferenceError
porque a variável está em uma "zona morta temporal" desde o início do bloco até a declaração ser processada.fonte
em es6, quando usamos let ou const, temos que declarar a variável antes de usá-las. por exemplo. 1 -
por exemplo. 2-
fonte