Проблема не в том, что x
объявляется дважды.Просто вы пытаетесь получить доступ к внутреннему x
до его инициализации:
let x = x /* doesn't exist yet*/;
Есть ли еще x
во внешней области видимости (инициализаторы в цикле for
находятся внутри ихсобственная область) не имеет значения, x
будет ссылаться на переменную в текущей области, так как она уже была объявлена (из-за подъема), но еще не была инициализирована:
let x = 0; // irrelevant
{ // x gets declared as part of this scope
x; // thats an error too as x is not initialized yet
let x = 1; // initialization
x; // now it can be accessed
}
часть между началом области и объявлением let
называется «временной мертвой зоной» ...
"... в цикле for выражение инициализатора вычисляется вне областиновой переменной "
Нет, иначе вы не могли бы ссылаться на другие переменные в инициализаторе:
for(let a = 1, b = a; ; )
Как всегда, определенный ответ можно найти в спецификации:
13.7.4.7 Семантика времени выполнения: LabelledEvaluation
IterationStatement: for (выражение LexicalDeclaration; выражение)
Пусть oldEnv будет исполняющимLexicalEnvironment контекста.
Пусть loopEnv будет NewDeclarativeEnvironment (oldEnv).
[...]
Пусть boundNames будет именем привязки в LexicalDeclaration.
Для каждого элемента dn of boundNames [..]
Выполните!loopEnvRec.CreateImmutableBinding (dn, true).
Установите для LexicalEnvironment контекста выполнения значение loopEnv.
Пусть forDcl будет результатом оценки LexicalDeclaration.
[...]
Как видите, контекст текущего выполнения равен loopEnv
, в то время как LexicalDeclaration (инициализаторы) оценивается,не oldEnv
.
TLDR: не только пример неправильный, но и параграф.