@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.