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()
, возникает ошибка.