Чем объясняется такое поведение?(Когда создаются функции?) - PullRequest
5 голосов
/ 07 сентября 2011

Код, о котором идет речь, прост:

console.log("So it begins.");
foo();
function foo() { console.log("In foo()."); }
console.log("So it ends.");

Почему foo() выполняется до его определения (ретроспективное редактирование: в Chrome и Safari)?

Я немного повозился с этим, тестируя следующий код в Chrome, Safari и Firefox:

javascript:foo();function foo() { alert("Oh."); }

Предупреждение отображается в Chrome и Safari, а Firefox хранит молчание.

Есть ли объяснение этому удивительному, непоследовательному поведению?

Ответы [ 3 ]

8 голосов
/ 07 сентября 2011

Jlaascript Delarations всегда будет перемещен на вершину.Это называется подъем :

Пример, который должен работать во всех браузерах: http://jsbin.com/abelus/edit

3 голосов
/ 07 сентября 2011

В то время как другие объяснили поведение «поднятия» функций (я лично нахожу это так: подготовка контекста или предварительная обработка более понятна, чем подъем ) причина о другом поведении 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 определяется как объявление функции, так как оно существует в теле анонимной функции и не является частью блока операторов.

3 голосов
/ 07 сентября 2011

Наблюдаемое вами поведение называется подъем функции .

В двух словах, функции, которые определены с использованием синтаксиса function foo() { ... }, «поднимаются» в верхнюю часть области действиякоторые они определили, что позволяет им вызываться до того, как их определят.

С учетом сказанного, это неясная часть JavaScript.Меня не удивит, если есть различия в том, как браузеры реализуют это (особенно если вы используете более старую версию Firefox).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...