Ответ 1
Насколько я вижу,
strict
относится к внутреннему слоту[[Strict]]
объекта функции.
И да. Это относится к строгости функции (или скрипта), в которой происходит блок, содержащий объявление функции. Не в строгости функции, которая должна (или не должна) быть объявлена.
"Веб-расширения" применимы только к небрежному (нестрогому) коду и только в том случае, если внешний вид оператора функции "нормальный", то есть, например, если его имя не вступает в противоречие с формальным параметром или лексически объявленная переменная.
Обратите внимание, что нет разницы между строгим и небрежным кодом без семантики веб-совместимости. В чистом ES6 только одно поведение для объявлений функций в блоках.
Таким образом, мы в основном имеем
| web-compat pure
-----------------+---------------------------------------------
strict mode ES6 | block hoisting block hoisting
sloppy mode ES6 | it complicated ¹ block hoisting
strict mode ES5 | undefined behavior ² SyntaxError
sloppy mode ES5 | undefined behavior ³ SyntaxError
1: смотри ниже.Предупреждения запрашиваются.
2: Как правило, SyntaxError
выбрасывается
3: примечание в ES5.1 §12 говорит о "значительных и непримиримых вариациях среди реализаций" (таких как эти).Предупреждения рекомендуются.
Так как же теперь реализация ES6 с веб-совместимостью ведет себя для объявления функции в блоке в функции с неаккуратным режимом с унаследованной семантикой?
Прежде всего, чистая семантика все еще применяется. То есть объявление функции поднимается до верха лексического блока.
Тем не менее, существует также объявление var
, которое выводится наверх функции включения.
И когда вычисляется объявление функции (в блоке, как если бы оно было выполнено как инструкция), объект функции присваивается этой переменной области действия.
Это лучше объяснить с помощью кода:
function enclosing(…) {
…
{
…
function compat(…) { … }
…
}
…
}
работает так же, как
function enclosing(…) {
var compat₀ = undefined; // function-scoped
…
{
let compat₁ = function compat(…) { … }; // block-scoped
…
compat₀ = compat₁;
…
}
…
}
Да, это немного сбивает с толку, имея две разные привязки (обозначенные индексами 0 и 1) с одним и тем же именем. Теперь я могу кратко ответить на ваши вопросы:
Видимо за пределами блока?
Да, как var
. Однако существует вторая привязка, которая видна только внутри блока.
Водрузили?
Да - дважды.
До какой точки?
Как для функции (однако инициализируется с помощью undefined
), так и для блока (инициализируется с помощью объекта функции).
"Протяжен"?
Не в смысле временной мертвой зоны объявленной лексически переменной (let
/const
/class
), которая генерирует ссылки, нет. Но до того, как объявление функции встретится при выполнении тела, переменная области действия не undefined
(особенно перед блоком), и вы также получите исключение, если попытаетесь вызвать ее.
Просто для справки: в ES6 описанное выше поведение было задано только для блоков в областях действия функций. С ES7 то же самое относится к блокам в eval
и global областях.