Функция объявления обрабатываются при входе в исполняемый контекст (например, глобальный контекст или вызов функции) перед обработкой любого пошагового кода в контексте.
Итак, в вашем коде происходят следующие вещи (в следующем порядке):
- «Переменный объект» создается для контекста выполнения.
- Записи (на самом деле,буквально, свойства) в «объекте переменной» создаются для каждого
var
и объявления функции в контексте (плюс несколько других вещей).В вашем случае это f1
и f2
.Изначально свойства имеют значение undefined
. - Все функции Объявления обрабатываются, и поэтому:
- Функция
f1
определена и назначена ее свойству вобъект переменной. - Функция
f2
определена и присвоена ее свойству объекта переменной.
- Выполнена строка
f1();
, вызывающая f1
function. - Код
f1
ссылается на f2
, который он получает от объекта переменной, и поэтому мы ожидаем, что он будет (ссылка на функцию f2
).
Более интересная версия такова:
f1();
function f1(){var a = 1; f2();}
function f2(){return a;}
... что происходит в точно в том же порядке , как указано выше, потому что оба объявления обрабатываютсяперед первой строкой пошагового кода.
Функция Объявления отличаются от функции выражений , которые, как и любое другое выражение, оцениваются, когда онидостигнуто в пошаговом исполнении сода.Функция выражение - это любое время, когда вы создаете функцию и используете ее как правое значение , например, присваиваете результат переменной или передаете его в другую функцию.Например:
var f2 = function() {
};
или
setTimeout(function() {
alert("Hi there");
}, 1000);
Обратите внимание, что мы используем результат оператора function
в качестве значения справа (в присваивании илипередавая это в функцию).Они не предварительно обрабатываются при входе в контекст выполнения (например, не на шаге 3 выше), они обрабатываются, когда поток кода достигает их.Что приводит к:
f1();
function f1(){var a = 1; f2();}
var f2 = function(){return a;};
... что не удается, потому что f2
не определено с момента его вызова.
Вы можете использовать значение объявленной функции в качестве значения для правой рукине превращая его в выражение функции (мы делаем это все время), при условии, что вы делаете это в двух отдельных операторах.Итак:
alert("Beginning");
function foo() { ... }
setTimeout(foo, 100);
Это происходит в следующем порядке:
foo
создается (поскольку это определено объявлением). alert
бежит. setTimeout
бежит. - (позже)
foo
вызывается.
Последний пункт: хотя они должны work, выражение функции, которое включает функцию name , работает не надежно во всех реализациях, и на данный момент его следует избегать:
var f = function foo() { ... }; // <== DON'T DO THIS
или
setTimeout(function foo() { // <== DON'T DO THIS
}, 1000);
Internet Explorer, в частности, имеет проблемы с ними, а также другие реализации в разное время.
Дополнительные сведения: