Ответ 1
Прежде всего, расскажите о том, чего мы ожидаем.
Я бы наивно ожидал, что оба случая вернут undefined
.
-
Также как:
eval("function foo(){}")
, который возвращает undefined. -
Как и всякий раз, когда у нас есть объявление функции, оно не возвращает значение функции, но устанавливает его.
- Так же, как спецификация langue говорит о строгом режиме.
Обновление: после того, как вы выкапываете больше через spec - Firefox здесь.
Вот что делает Firefox
Визуализация:
- f
= eval("" + f);
//установите левую сторону в функциюf
, мы находимся вf =
eval ("" + f);//объявить новую функциюf
в рамках этой функцииf = undefined;
//посколькуundefined === eval("function(){}");
*
*, поскольку объявления функций ничего не возвращают - точно так же, как функция foo() {} не имеет возвращаемое значение
Так как f было принято на шаге 1, прямо сейчас ссылка на функцию, в которой мы находимся, была перезаписана с помощью undefined, а объявленное локальное закрытие f
было объявлено с тем же кодом.
Теперь, когда мы делаем:
console.log("Inside a call to f(), f is: \n%s",
f)
//f - локальная переменная закрытия, ближайшая
Внезапно очевидно, что мы получаем функцию - это переменная-член.
Однако, как только мы выйдем из функции
console.log("After a call to f(), f is: \n%s",
е);
Здесь f является undefined, поскольку мы перезаписали его на шаге 1.
Chrome и IE делают ошибку, присваивая ей неправильный f
и оценивая правую сторону перед левой стороной задания.
Почему он работает в строгом режиме
Обратите внимание, что в следующем разделе говорится о вводе кода eval:
Пусть strictVarEnv будет результатом вызова NewDeclarativeEnvironment, передающего LexicalEnvironment в качестве аргумента.
Это объясняет, почему он работает в строгом режиме - все это выполняется в новом контексте.
То же самое, но в большем количестве текста и менее графически
- "Найти"
f
изf =
(так как сначала нужно оценить левую сторону. Это относится к локальной копииf
. То есть сначала оценивайте левую сторону. - Выполните вызов
eval
, который возвращаетundefined
, но объявляет новую локальную функциюf
. - Так как
f
изf =
оценивался до самой функции, когда мы присваиваем ей undefined, мы фактически заменяем глобальную функцию - Итак, когда мы делаем
console.log
внутри, мы имеем в виду локальную копию, объявленную в eval, поскольку она ближе в цепочке областей видимости. - Когда мы находимся снаружи и делаем
console.log
, теперь мы ссылаемся на "глобальный"f
, который мы назначили undefined to.
Фокус в том, что мы назначаем f, а f, который мы регистрируем, - это два разных fs. Это связано с тем, что левая часть задания всегда оценивается сначала (с 11.13.1 в спецификации).
IE и Chrome делают ошибку при назначении локальному f
. Это явно неверно, поскольку в спецификации четко сказано:
Пусть lref является результатом оценки LeftHandSideExpression.
Пусть rref является результатом вычисления AssignmentExpression.
Итак, поскольку мы видим, что сначала необходимо оценить lref.