tl; dr Если вы ничего не звоните, пока все не загрузится, все будет в порядке.
Изменить: для обзора, который также охватывает некоторые объявления ES6 ( let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
Это странное поведение зависит от
- Как вы определяете функции и
- Когда вы им звоните.
Вот несколько примеров.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
Это из-за того, что называется подъемом !
Есть два способа определения функций: объявление функции и выражение функции . Разница раздражает и минуты, так что давайте просто сказать , что это немного не то: Если вы пишете это как function name() {}, это заявление , и , когда вы пишете , как var name = function() {}(или анонимную функцию , назначенную к возвращению, и тому подобное), это выражение функции .
Во-первых, давайте посмотрим, как обрабатываются переменные:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Теперь, как обрабатываются объявления функций :
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
В varведомости «кидает» на создание в fooдо самого верха, но не присваивает значение для нее еще. Далее следует объявление функции, и, наконец, ей присваивается значение foo.
А что насчет этого?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
В начало перемещается только объявление of foo. Присваивание происходит только после вызова bar, где оно было до того, как все подъемы произошли.
И напоследок для краткости:
bar();
function bar() {}
//turns to
function bar() {}
bar();
А что насчет функциональных выражений ?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Так же , как и обычные переменные, первый fooбудет объявлен в высшей точке сферы, то ему присваивается значение.
Посмотрим, почему второй пример выдает ошибку.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
Как мы видели ранее, fooподнимается только создание объекта , а присваивание происходит там, где оно появилось в «исходном» (не поднятом) коде. Когда barвызывается, ему до этого fooприсваивается значение, поэтому foo === undefined. Теперь в теле функции bar, как будто вы это делаете undefined(), возникает ошибка.