confuso sobre a declaração de função em {}

18

var a;
if (true) {
  a = 5;

  function a() {}
  a = 0;
  console.log(a)
}
console.log(a)

Eu vi o código acima, uma função é declarada em {}. Eu acho que imprimiria 0 0, mas imprime 0 5

Marcus Lee
fonte
11
No modo estrito, ele registra 0 undefined.
CertainPerformance 30/10/19
Bem, isso é explicável, mas não consigo explicar que a = 5deixa o bloco. Segundo bergi no dupe, function aserá içada.
Jonas Wilms
2
Parece que a variável de bloco com escopo local é copiada para o bloco externo ao atingir a declaração da função.
Jonas Wilms

Respostas:

13

O seguinte acontece:

(1) Existem duas declarações de variáveis a, uma dentro do bloco e outra fora dele.

(2) A declaração da função é içada e vinculada à variável de blocos internos.

(3) a = 5é alcançado, que substitui a variável de bloco.

(4) a declaração de função é alcançada e a variável de bloco é copiada para a variável externa. Ambos são 5 agora.

(5) a = 0é alcançado, que substitui a variável de bloco. A variável externa não é afetada por isso.

 var a¹;
 if (true) {
   function a²() {} // hoisted
   a² = 5;
   a¹ = a²; // at the location of the declaration, the variable leaves the block      
   a² = 0;
  console.log(a²)
}
console.log(a¹);

Na verdade, isso não faz parte da especificação, faz parte da semântica de compatibilidade herdada da Web ; portanto , não declare funções dentro de blocos e não confie nesse código para se comportar dessa maneira .

Isso também é explicado aqui

Jonas Wilms
fonte
Mas por que, uma vez atingida a declaração da função, a variável de bloco será copiada para a variável externa? Concluiu isso do depurador?
Chor
@ Não, a especificação diz isso. Eu não tenho ideia do porquê.
Jonas Wilms