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