Где хранится запись неизменяемой привязки идентификатора в выражении именованной функции в JavaScript?
Недавно я столкнулся с некоторыми интересными фактами о выражениях именованных функций (NFE). Я понимаю, что к имени функции NFE можно получить доступ в теле функции, что делает рекурсию более удобной и спасает насarguments.callee
, И имя функции не доступно вне тела функции. Например,
var foo = function bar() {
console.log(typeof bar);
};
typeof foo; // 'function'
typeof bar; // 'undefined', inaccessible outside the NFE
foo(); // 'function', accessible inside the NFE
Это хорошо документированная функция, и у Кангаксасообщение про НФЭ и упомянул это явление там. Что меня больше всего удивляет, так это то, что имя функции NFE не может быть связано с другими значениями в теле функции. Например,
(function foo() {
foo = 5;
alert(foo);
})(); // will alert function code instead of 5
В приведенном выше примере мы попытались повторно привязать идентификаторfoo
с другим значением5
, Но это не удалось! И я обратился к ES5 Spec и обнаружил, что запись неизменяемой привязки была создана и добавлена в записи среды лексической среды при создании NFE.
Проблема в том, что когда NFE ссылается на собственное имя функции внутри тела функции, имя было разрешено каксвободная переменная, В приведенном выше примереfoo
упоминается внутри NFE, но не является ни формальным параметром, ни локальной переменной этой функции. Так что это свободная переменная и ее запись привязки может быть разрешена через свойство [[scope]] NFE.
Итак, учтите это, если у нас есть другой идентификатор с таким же именем во внешней области видимости, кажется, что существует некоторый конфликт. Например,
var foo = 1;
(function foo() {
alert(foo);
})(); // will alert function code rather than 1
alert(foo); // 1
Когда мы выполняем NFE,свободная переменная foo
был преобразован в функцию, с которой он связан. Но когда контроль выходит из контекста NFE,foo
была решена как локальная переменная во внешней области видимости.
Итак, мой вопрос заключается в следующем:
Где хранится запись неизменяемой привязки имени функции?Как получилось название функцииfoo
перевешиватьvar foo = 1
когда разрешено внутри НФЭ? Хранятся ли их обязательные записи в одной и той же лексической среде? Если так, то как?Что стоит за феноменом, который называют функциейfoo
доступен внутри, но невидим снаружи?Может кто-нибудь пролить свет на это с ES5 spec? Я не нахожу много дискуссий в Интернете.