Почему имя функции внутри именованной функции в JavaScript больше не ссылается на саму функцию?
Рассмотрим следующую именованную функцию:
function f() {
return f.apply(this, arguments);
}
Если вы вызываете эту функцию нормально, это приведет к переполнению стека, как и ожидалось. Не очень интересно Итак, давайте сделаем немного магии:
var g = f, f = alert;
Теперь, если вы позвоните f
это будет просто alert
первый аргумент. Однако если вы позвоните g
это все еще будет alert
первый аргумент. Что происходит? Не должен звонить g
привести к переполнению стека?
Я понимаю, что внутри функции f
(сейчас g
) переменная f
больше не связан с f
, Это становится свободной переменной. Следовательно внутри f
переменная f
сейчас указывает на alert
,
Почему это происходит? Я ожидаю, что имя функции внутри именованной функции всегда будет ссылаться на саму функцию. Я не жалуюсь. Это на самом деле довольно круто. Мне просто интересно.
2 ответа
Когда вы делаете:
var g = f
Это фактически так же, как:
var g = function () {
return f.apply(this, arguments);
}
Тем не менее, так как вы переназначены f
он больше не указывает на исходную функцию, теперь он указывает на alert
, Похоже, он работает как задумано.
Как уже упоминалось в других ответах, это так, как задумано. По сути, кроме подъема, объявление делает это:
var f = function () {
return f.apply(this, arguments);
}
То есть ценность f
разрешается не в объявлении, а во время вызова функции. Вот почему вы видите то, что видите.
Но есть способ заставить его вести себя так, как вы хотите: использовать выражение с именованной функцией. Выражение именованной функции выглядит как объявление, но не потому, что функция объявлена как выражение.
Например, в следующем:
var ff = function f () {
return f.apply(this, arguments);
}
Значение f
связан в декларации и будет неуязвимым для переназначения. В выражении именованной функции имя функции определяется только внутри выражения и поэтому ведет себя скорее как замыкание, а не как переменная.