Порядок функций в JavaScript - PullRequest
       12

Порядок функций в JavaScript

7 голосов
/ 23 декабря 2010

Мой вопрос основан на примере из книги « Объектно-ориентированный JavaScript » (стр. 81 - Lexical Scope)

Итак, я понимаю из этого примера ...

function f1(){var a = 1; f2();}
function f2(){return a;}
f1();

... что:

а не определено

Но как f1 узнает о f2, который определяется после f1?

Такое поведение вызывает вопрос:

Как работает интерпретатор JavaScript?

Я предполагаю, что это:

  1. сканирует код и просто сохраняет функции, не назначенные никаким переменным, в глобальной среде
  2. Вызывает функцию в режиме ad-hoc: если такой функции нет в глобальной среде, тогда жаловаться.

Ответы [ 2 ]

16 голосов
/ 23 декабря 2010

Функция объявления обрабатываются при входе в исполняемый контекст (например, глобальный контекст или вызов функции) перед обработкой любого пошагового кода в контексте.

Итак, в вашем коде происходят следующие вещи (в следующем порядке):

  1. «Переменный объект» создается для контекста выполнения.
  2. Записи (на самом деле,буквально, свойства) в «объекте переменной» создаются для каждого var и объявления функции в контексте (плюс несколько других вещей).В вашем случае это f1 и f2.Изначально свойства имеют значение undefined.
  3. Все функции Объявления обрабатываются, и поэтому:
    • Функция f1 определена и назначена ее свойству вобъект переменной.
    • Функция f2 определена и присвоена ее свойству объекта переменной.
  4. Выполнена строка f1();, вызывающая f1 function.
  5. Код 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);

Это происходит в следующем порядке:

  1. foo создается (поскольку это определено объявлением).
  2. alertбежит.
  3. setTimeout бежит.
  4. (позже) foo вызывается.

Последний пункт: хотя они должны work, выражение функции, которое включает функцию name , работает не надежно во всех реализациях, и на данный момент его следует избегать:

var f = function foo() { ... }; // <== DON'T DO THIS

или

setTimeout(function foo() {     // <== DON'T DO THIS
}, 1000);

Internet Explorer, в частности, имеет проблемы с ними, а также другие реализации в разное время.

Дополнительные сведения:

0 голосов
/ 23 декабря 2010

у вас нет доступа к переменной 'a' внутри функции f1, потому что функция f2 не определена внутри области видимости f1

если вы определяете f2 внутри f1:

function f1(){function f2(){return a;} var a = 1; f2();}
f1();

у вас нет проблем

...