Я не буду требовать понимания всех тонкостей, но главное в этом почти странные искажения в Приложении B §B.3.3.1.
Этот код эффективно это, где f1
является второй копией f
специфичны для лексического окружения блока (отсюда let
ниже):
var p =() => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
var f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
И, конечно, благодаря var
грузоподъемных, как p
и f
эффективно объявлены в верхней части фрагмента кода с начальным значением undefined
:
var f = undefined;
var p = undefined;
p =() => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
ключ от битового В.3.3.1 заключается в том, что он переносит значение внутреннего f
(которое я назвал f1
выше) на внешний (ниже, F - строка "f"
, название объявляемой функции):
3. Когда FunctionDeclaration е вычисляется, выполнить следующие шаги вместо алгоритма FunctionDeclaration оценки, представленной в 14.1.21:
с. Пусть fenv - переменная среды выполнения контекста выполнения.
b. Пусть fenvRec be fenv's EnvironmentRecord.
c. Пусть benv - это лексическое окружение контекста выполнения выполнения.
d. Пусть benvRec beben's EnvironmentRecord.
e. Let fobj be! benvRec.GetBindingValue (F, false).
f. Выполните! fenvRec.SetMutableBinding (F, fobj, false).
g. Возврат NormalCompletion (пустой).
Напомним, что окружающая среда переменная является функцией шириной, но среда лексической более ограничена (в блоке).
Когда дело доходит до попытки нормализовать объявления функций в местах, где они были {недействительными | unspecified} (выберите ваш термин), TC39 имеют очень предательский путь для навигации, стараясь стандартизировать поведение, не нарушая существующий код, который, возможно, полагался на поведение, специфичное для исполнения, из прошлого (которые были взаимоисключающими, но TC39 пытается добиться баланса).
В частности, относительно хостинга? Этот ответ объясняет это очень хорошо: http://stackoverflow.com/questions/25111087/why-is-a-function-declaration-within-a-condition-block-hoisted-to-function-scope – CodingIntrigue
@CodingIntrigue: Нет, который не охватывает то, что происходит выше, что является артефактом Приложения B ES2015 и TC39, которые изо всех сил пытаются справиться с серьезными коварными водами существующего кода и исторически несогласованными реализациями. :-) –
@ T.J.Crowder Уход, чтобы объяснить более подробно? 'function f() {}' обычно будет подниматься внутри нормального функционального блока, а первый 'undefined' должен был напечатать декларацию функции f, но как теперь это определено внутри блока? – kstratis