#javascript #parameters #scope #language-lawyer
Вопрос:
Следующий код всегда выводит аргумент , переданный параметру a
, независимо от наличия переменной с тем же именем.
Предположительно, потому, что идентификаторы параметров привязаны отдельно к переменным в области видимости. Где они расположены? Находятся ли они в лексической среде?
function foo(a, b = () => a) {
var a = 1
console.log(b())
}
foo() // undefined
foo(2) // 2
Является ли это тем, что var
объявления попадают в специальную переменную среду, в то время как параметры располагаются в лексической среде? И let
и const
избежать конфликта, сделав переопределение ранней ошибкой?
Уместно также:
Комментарии:
1.Список параметров, как я понимаю, имеет свою собственную область действия. Закрытие для этой
=>
функции имеет параметрa
в области действия.2. Я думаю, что это часть статической семантики . «Связанные имена» из списка параметров добавляются в набор для следующего параметра в списке формальных параметров. Однако я не на 100% уверен, что смотрю на правильную вещь, потому что я только наполовину выпил чашку кофе.
3. Конечно, все становится намного сложнее, когда вы рассматриваете синтаксис деструкции в списке параметров, но это похоже на то, что слева направо для каждой позиции привязки в списке формальных параметров появляется новая лексическая область, а область действия функции-это еще один лексический слой.
4. Иногда это помогает подтвердить ожидаемое поведение различных взаимодействующих семантик, просто поместив их в babel и посмотрев на вывод ES5, о котором обычно легче рассуждать. Но чтобы объяснить мой предыдущий комментарий, используйте
let
вместоvar
генерирует aSyntaxError
, что я нахожу гораздо предпочтительнееvar
, чем приведенное выше неявное затенение записи среды списка параметров.5. @52d6c6af эта семантика на самом деле не соотносится один к одному с наблюдаемыми объектами в языке. Нет, я не верю, что это связано с
arguments
объектом, так как поведение идентично при переходеfoo
на функцию со стрелкой.
Ответ №1:
В случае наличия любых значений по умолчанию для параметров создается отдельная запись среды.
Семантика функций, объявленных в этой позиции, такова, что эта запись среды определяет их локальную область действия. В примечании к спецификации (см. пункт 28) говорится::
ПРИМЕЧАНИЕ. Отдельная запись среды необходима для обеспечения того, чтобы замыкания, созданные выражениями в списке формальных параметров, не отображали объявления в теле функции.
Подробнее из спецификации:
Когда устанавливается контекст выполнения для оценки функции ECMAScript, создается новая запись среды функции, и в этой записи среды создаются привязки для каждого формального параметра. Каждое объявление в теле функции также создается экземпляр. Если формальные параметры функции не включают инициализаторы значений по умолчанию, то объявления тела создаются в той же записи среды, что и параметры. Если существуют инициализаторы параметров значения по умолчанию, для объявлений тела создается вторая запись среды. Формальные параметры и функции инициализируются как часть functiondeclarationустановки. Все остальные привязки инициализируются во время оценки тела функции.
Поэтому в отсутствие аргументов по умолчанию я делаю вывод, что для привязки параметров используется одна из ранее существовавших лексических сред (VariableEnvironment или LexicalEnvironment). Может быть.