Мой вопрос касается спецификации ECMAScript.
В настоящее время я следую спецификации, чтобы понять, как простой сценарий оценивается от начала до конца.
Следуя этому вопросу и ответу , я просматриваю GlobalDeclarationInstantiation, чтобы увидеть, как создается экземпляр FunctionDeclaration (идентификатор добавляется в глобальную запись среды (GER)) и инициализируется (значение добавляется к идентификатору в GER). ).
Это подводит меня к шагу 5 GlobalDeclarationInstantiation: Let varDeclarations be the VarScopedDeclarations of script..
Глядя на VarScopedDeclarations , мне кажется, что он никогда не возвращает Parse Node для FunctionDeclaration. Фактически он возвращает пустые списки для всех символов синтаксической грамматики, кроме VarDeclarations. Это означает, что он возвращает узлы разбора только для символов, следующих за ключевым словом var. VarScopedDeclarations из var a = 5 вернет узел разбора, содержащий a = 5.
Вопросы
i. Assert: d is either a FunctionDeclaration...) когда-либо положительным утверждением?


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Глядя на VarScopedDeclarations, мне кажется, что он никогда не возвращает Parse Node для FunctionDeclaration. Фактически он возвращает пустые списки для всех символов синтаксической грамматики, кроме VarDeclarations.
Я думаю, вы пропустили несколько битов:
FunctionStatementList : StatementList
1. Return the TopLevelVarScopedDeclarations of StatementList.
ClassStaticBlockStatementList : StatementList
1. Return the TopLevelVarScopedDeclarations of StatementList.
ScriptBody : StatementList
1. Return TopLevelVarScopedDeclarations of StatementList.
И тогда TopLevelVarScopedDeclarations действительно возвращает то, что вы ожидали, объявления функций, которые должны быть подняты:
StatementListItem : Declaration
1. If Declaration is Declaration : HoistableDeclaration , then
a. Let declaration be DeclarationPart of HoistableDeclaration.
b. Return « declaration ».
2. Return a new empty List.
LabelledItem : FunctionDeclaration
1. Return « FunctionDeclaration ».
(где HoistableDeclaration — любое из FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration)
Возможно, вас смутило правило VarScopedDeclarations.
StatementListItem : Declaration
1. Return a new empty List.
Да, это не возвращает объявлений функций, но это правило применяется только к объектам StatementListItem внутри блока или блока CaseBlock. VarScopedDeclarations выполняет рекурсию в блоки, но только для того, чтобы найти там VariableDeclarations, а не для поиска объявлений функций — они не поднимаются из блоков.
Спасибо! Что касается вашего последнего замечания: возможно, я неправильно читаю грамматику, но мне кажется, что StatementListItem может встречаться внутри StatementList (пункт 14.2 Блок), а StatementList может встречаться в самых разных местах (не только внутри блока). Таким образом, как вы можете сделать вывод, что объект StatementListItem, упомянутый в * VarScopedDeclarations*, относится к объекту StatementListItem внутри блока?
@Magnus Ах, хороший звонок, я слишком рано сделал вывод. Но на самом деле не так уж и много разных мест — есть только Block, CaseBlock, FunctionStatementList, ClassStaticBlockStatementList и ScriptBody. И последние три явно делегируют TopLevelVarScopedDeclarations, который не рекурсивно. Tbh, я думаю, что рекурсия была бы чище (и проще для понимания), если бы соответствующие алгоритмы …DeclarationInstantiation напрямую вызывали бы TopLevelVarScopedDeclarations, которые затем делегировали бы рекурсивную InnerVarScopedDeclarations операцию.
Действительно, @Bergi. Является ли это конфликтом в VarScopedDeclarations: StatementListItem может возникать в StatementList, который может возникать в FunctionStatementList. Таким образом, объявление (например, FunctionDeclaration) в FunctionStatementList должно возвращать пустой список. Однако далее в VarScopedDeclarations написано: FunctionStatementList : StatementList -> Return "FunctionDeclaration" (через TopLevelVarScopedDeclarations). Есть идеи, что мне не хватает?
«Таким образом, объявление в FunctionStatementList должно возвращать пустой список» — только если вы должны были вызвать VarScopedDeclarations непосредственно в StatementList функции. Но этого не происходит, VarScopedDeclarations вызывается в FunctionStatementList, и правило для этого заставляет возвращать объявления (через TopLevelVarScopedDeclarations).
Не уверен, что вы получили уведомление, но я создал комнату с парой дополнительных вопросов, если/когда у вас будет время. Возможно, это ценно и для других. Ссылка: chat.stackoverflow.com/rooms/250378/room-for-magnus-and-bergi
О, они изменили это, раньше (ES6) это было разбросано по всей спецификации… Отлично!