As variables ​​declaradas com let ou const não são hasteadas no ES6?

Eu tenho jogado com ES6 por um tempo e notei que enquanto variables ​​declaradas com var são içadas como esperado …

 console.log(typeof name); // undefined var name = "John"; 

… variables ​​declaradas com let ou const parecem ter alguns problemas com içamento:

 console.log(typeof name); // ReferenceError let name = "John"; 

e

 console.log(typeof name); // ReferenceError const name = "John"; 

Isso significa que as variables ​​declaradas com let ou const não são içadas? O que realmente está acontecendo aqui? Existe alguma diferença entre let e const nesta questão?

@thefourtheye está correto ao dizer que essas variables não podem ser acessadas antes de serem declaradas. No entanto, é um pouco mais complicado do que isso.

As variables ​​são declaradas com let ou const não hasteadas? O que realmente está acontecendo aqui?

Todas as declarações ( var , let , const , function , function* , class ) são “hasteadas” 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 é verdadeiro para escopos de function e bloco 1 .

A diferença entre as declarações var / function / function* e as declarações let / const / class é a boot .
Os primeiros são inicializados com undefined ou a function (gerador), quando a binding é criada no topo do escopo. As variables ​​declaradas lexicamente, no entanto, permanecem não inicializadas . Isso significa que uma exceção ReferenceError é 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 um let y; instrução inicializa a variável com undefined como let y = undefined; teria.

A zona morta temporal não é uma localização sintática, mas sim o tempo entre a criação da variável (escopo) e a boot. 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 da function ou simplesmente código morto), e ele lançará uma exceção se você acessar a variável antes da boot, mesmo que o access o código está abaixo da declaração (por exemplo, em uma declaração de function hasteada que é chamada cedo demais).

Existe alguma diferença entre let e const nesta questão?

Não, eles funcionam da mesma maneira que o içamento é considerado. A única diferença entre eles é que uma const deve ser e só pode ser atribuída na parte do inicializador da declaração ( const one = 1; ambos const one; e posteriores reatribuições como one = 2 são inválidos).

1: declarações var ainda estão funcionando apenas no nível da function, é claro

Citando a especificação do ECMAScript 6 (ECMAScript 2015), a seção let e const ,

As variables ​​são criadas quando seu ambiente lexical é instanciado, mas não pode ser acessado de forma alguma até que o LexicalBinding da variável seja avaliado .

Portanto, para responder à sua pergunta, sim, let e const aumentando, mas você não pode acessá-los antes que a declaração real seja avaliada em tempo de execução.

ES6 introduz as variables Let que surgem com o block level scoping . Até o ES5 não tínhamos block level scoping , então as variables ​​que são declaradas dentro de um bloco são sempre hoisted para o escopo do nível de function.

Basicamente, o Scope refere-se a onde, em seu programa, suas variables ​​são visíveis, o que determina onde você pode usar as variables ​​declaradas. No ES5 temos global scope,function scope and try/catch scope , com ES6 também obtemos o escopo de nível de bloco usando Let.

  • Quando você define uma variável com var keyword, é conhecida toda a function a partir do momento em que é definida.
  • Quando você define uma variável com a instrução let , ela é conhecida apenas no bloco que está definida.

      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 

Se você executar o código, poderá ver que a variável j só é conhecida no loop e não antes e depois. No entanto, nossa variável i é conhecida em entire function partir do momento em que é definida em diante.

Há outra grande vantagem ao usar o let, pois ele cria um novo ambiente léxico e também vincula o valor novo em vez de manter uma referência antiga.

 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) } 

O primeiro loop for sempre imprime o último valor, com ele cria um novo escopo e liga valores novos nos imprimindo 1, 2, 3, 4, 5 .

Chegando às constants , funciona basicamente como let , a única diferença é que seu valor não pode ser alterado. Em constantes, a mutação é permitida, mas a reconsignação não é 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); 

Se uma constante se refere a um object , ele sempre se referirá ao object mas o próprio object pode ser alterado (se for mutável). Se você gosta de ter um object imutável, você poderia usar Object.freeze([])