Поднимаются ли внутренние функции в JavaScript? Как к ним применяются правила области видимости?

Я думал, что в JavaScript область действия не блочная, а функциональная, и что объявления поднимаются из своего блока в начало своих родительских функций.

Однако следующий код не работает должным образом:

function one(a) {
    console.log("one called for " + a);

    if (a == 1) {
        function inner(b) {
            console.log("inner called for " + b);
        }

        inner(123);
    }

    inner(456);
}

one(1);
one(2);
one(3);

Первый вызов one(1); проходит нормально, без ошибок, однако выполнение останавливается при вызове второго one(2);.

Это поведение интуитивно понятно: функция inner определяется только в том случае, если a==1.

Но как это согласуется с правилами области видимости/поднятия?

Я думал, что его определение будет поднято наверх его области видимости, за пределы блока if, который, как предполагается, не будет иметь никакого эффекта!

Изменить: вот ошибки, которые я получаю:

скриншот консоли Firefox, показывающий ошибку

Браузер — Firefox. Поиграйте здесь.


person corazza    schedule 24.02.2014    source источник
comment
У меня сработало - jsfiddle.net/Ls5sP   -  person Mark Walters    schedule 24.02.2014
comment
@MarkWalters Еще раз взгляните на консоль. Есть ошибки.   -  person Andy    schedule 24.02.2014
comment
Уверяю вас, в консоли нет ошибок   -  person Mark Walters    schedule 24.02.2014
comment
Ну, я смотрю на твою скрипку и там есть :/   -  person Andy    schedule 24.02.2014
comment
В каком браузере вы находитесь?   -  person Mark Walters    schedule 24.02.2014
comment
Последняя версия Firefox с использованием Firebug.   -  person Andy    schedule 24.02.2014
comment
Посмотрите на вопрос, я опубликовал сообщение об ошибке в вашей скрипке. Я использую Nightly (Firefox).   -  person corazza    schedule 24.02.2014
comment
я использую хром, и я не получаю справочную ошибку для внутреннего не определено   -  person Mark Walters    schedule 24.02.2014
comment
@MarkWalters: делает вопрос более интересным: P   -  person corazza    schedule 24.02.2014
comment
Да, я не получаю его в Chrome.   -  person Andy    schedule 24.02.2014
comment
Вот еще один вопрос, который я нашел, который может пролить свет - stackoverflow.com/questions/20302057/   -  person Mark Walters    schedule 24.02.2014
comment
Вот ссылка на ошибку в Firefox — bugzilla.mozilla.org/show_bug.cgi?id =609832   -  person Mark Walters    schedule 24.02.2014
comment
У вас есть +1 Googlefu.   -  person Andy    schedule 24.02.2014
comment
В Chrome это работает нормально, но это пограничный код. Попробуйте использовать strict и рассматривайте только те браузеры, которые действительно на 100% соответствуют требованиям ES5.   -  person pid    schedule 24.02.2014
comment
@Энди Данке Шон. Я родился в Google!   -  person Mark Walters    schedule 24.02.2014


Ответы (2)


if (…) {
    function …() {            
        …
    }
}

является недопустимым ECMAScript. Объявления функций должны находиться на верхнем уровне тел функций или программ внутри блоков их блоков. поведение зависит от реализации. Firefox выполняет этот оператор функции условно, другие браузеры поднимают его как обычное объявление функции. Переместите его за пределы оператора if или назначьте функциональное выражение.

person Bergi    schedule 24.02.2014
comment
Объявления функций должны быть на верхнем уровне тела функции или программы — но разве пример, который вы разместили, не «на верхнем уровне функции»? - person corazza; 24.02.2014
comment
Нет, это внутри блока if-body - person Bergi; 24.02.2014

Объявление inner поднимается в начало внешней функции. Однако его значение устанавливается только в том случае, если a == 1.

Когда outer() вызывается с другим значением, вызов inner(456) завершается ошибкой, так как inner по-прежнему имеет значение undefined.

person Phylogenesis    schedule 24.02.2014