Порядок функций в JavaScript
Мой вопрос основан на примере из книги " Объектно-ориентированный JavaScript" (стр. 81 - Lexical Scope)
Итак, я понимаю из этого примера...
function f1(){var a = 1; f2();}
function f2(){return a;}
f1();
... тот:
а не определено
Но как f1 узнать о f2, который определяется после f1?
Такое поведение вызывает вопрос:
Как работает интерпретатор JavaScript?
Я предполагаю, что это:
- сканирует код и просто сохраняет функции, не назначенные ни одной переменной, в глобальной среде
- Вызывает функцию в режиме ad-hoc: если такой функции нет в глобальной среде, тогда жаловаться.
2 ответа
Объявления функций обрабатываются при входе в исполняемый контекст (например, глобальный контекст или вызов функции), перед обработкой любого пошагового кода в контексте.
Итак, в вашем коде такие вещи происходят (в следующем порядке):
- "Переменный объект" создается для контекста выполнения.
- Записи (на самом деле, буквально, свойства) в "переменном объекте" создаются для каждого
var
и объявление функции в контексте (плюс несколько других вещей). В вашем случае этоf1
а такжеf2
, Изначально свойства имеют значениеundefined
, - Все объявления функций обрабатываются, и так:
f1
Функция определяется и присваивается своему свойству объекта переменной.f2
Функция определяется и присваивается своему свойству объекта переменной.
f1();
строка выполняется, вызываяf1
функция.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
называется.
И последнее замечание: хотя они должны работать, выражение функции, которое включает имя функции, не работает надежно во всех реализациях, и на данный момент его следует избегать:
var f = function foo() { ... }; // <== DON'T DO THIS
Или же
setTimeout(function foo() { // <== DON'T DO THIS
}, 1000);
Internet Explorer, в частности, имеет проблемы с ними, а также другие реализации в разное время.
Больше для изучения:
- Плохо понял
var
- Замыкания не сложны (потому что они говорят о переменных объектах и о том, как разрешаются символы)
- Anonymouses anonymous (подробнее о выражениях именованных функций)
У вас нет доступа к переменной 'a' внутри функции f1, потому что функция f2 не определена в области видимости f1
если вы определяете f2 внутри f1:
function f1(){function f2(){return a;} var a = 1; f2();}
f1();
у тебя нет проблем