В то время как другие объяснили поведение «поднятия» функций (я лично нахожу это так: подготовка контекста или предварительная обработка более понятна, чем подъем ) причина о другом поведении Firefox остается без ответа.
Для начала вы должны знать разницу между объявлением функции и оператором функции .
Объявление функции, как в вашем примере, может происходить только в двух местах: в глобальном коде (вне какой-либо функции) и непосредственно в теле функции другой функции, например:
function foo () {}
function bar () {
function baz() {}
}
Все вышеперечисленные функции являются действительными объявлениями функций.
Спецификация ECMAScript не позволяет определять объявления функций в других местах, например, внутри блоков:
if (true) {
function foo () {}
}
Приведенная выше функция должна дать вам исключение SyntaxError
, но большинство реализаций доброжелательны, и они все равно будут предварительно обрабатывать (поднимать) функцию, даже если фактическая функция недоступна (например, if (false) { function bar() {} }
).
В Firefox Заявления функций разрешены, это означает, что определение функции действительно происходит, когда элемент управления достигает этого конкретного оператора, например:
if (true) {
function foo () { return true; }
} else {
function foo () { return false; }
}
Выполнение foo();
после вышеприведенных операторов в Firefox выдаст true
, потому что первая ветвь оператора if
фактически выполнена.
В других браузерах foo();
создает false
, поскольку все функции предварительно обрабатываются при входе в контекст выполнения, и последняя будет иметь приоритет, даже если ветвь false
оператора if
никогда достигнуто.
Консоль Firebug выполняет свой код, заключая его в блок try-catch
, поэтому функция недоступна до ее объявления.
Если вы попробуете на консоли:
console.log(typeof f); // "undefined"
function f () {}
Вы увидите, что f
еще не подготовлен, но если вы оберните свой код внутри функции, вы увидите ожидаемое поведение:
(function () {
console.log(typeof f); // "function"
function f () {}
})();
Опять же, это потому, что теперь f
определяется как объявление функции, так как оно существует в теле анонимной функции и не является частью блока операторов.