Подъем Javascript в Chrome и Firefox

Запуск этого в Chrome и Firefox дает разные ответы:

(function() {

        if(true) {
            function f() { alert("yes"); };
        } else {
            function f() { alert("no"); };
        }
        f();

    })();

В Chrome результат "нет" В Firefox результат "да"

Почему разница?

Ответ 1

Объявление функций внутри условных операторов нестандартно, поэтому не делать этого. Это известная проблема. Вы можете использовать выражения функций вместо деклараций:

var f;
if(true) {
    f = function() { alert("yes"); };
} else {
    f = function() { alert("no"); };
}
f();

знаменитая статья Kangax о выражениях функций дает дополнительные сведения:

ФункцияDeclarations разрешена только в Program или FunctionBody. Синтаксически они не могут отображаться в блоке ({ ... }) - например, в выражениях if, while или for. Это связано с тем, что Blocks может содержать только выражения, а не SourceElements, в функции FunctionDeclaration.

В той же статье также говорится:

Следует отметить, что в соответствии со спецификацией реализациям разрешено вводить расширения синтаксиса (см. раздел 16), но все же должны быть полностью совместимы. В наши дни это происходит именно так. Некоторые из них интерпретируют объявления функций в блоках как любые другие объявления функций - просто поднимая их на вершину охватывающей области; Другие - вводят различную семантику и следуют несколько более сложным правилам.

Ответ 2

От V8 (движок JavaScript Chrome) отслеживатель ошибок:

Не ошибка. Firefox - единственный браузер, который делает то, что вы ожидаете.

Поведение Safari и IE на этом же, как у Chrome/V8.

Ответ 3

Это происходит из-за недостаточной загрузки Firefox, как это предусмотрено в ECMAScript 5.

Chrome правильно присваивает значение f() перед запуском тела функции, поэтому первая версия f() перезаписывается второй.

SpiderMonkey (движок JavaScript Firefox) запускает код без предварительного назначения значения f(), поэтому он использует единственное значение, которое встречается на своем пути: function f() { alert("yes"); };

какая функция подъема?
Область действия JavaScripts означает, что все переменные, объявленные внутри функции, видны по всему телу функции. Любопытно, что это означает, что переменные равны видимые до их объявления. Эта особенность JavaScript неофициально известна как подъем: Код JavaScript ведет себя так, как будто все объявления переменных в функции (но не все связанные назначения) "поднимаются" в начало функции.

источники:
http://statichtml.com/2011/spidermonkey-function-hoisting.html
2011 - o'reilly - javascript - окончательное руководство 6-го издания