2013-12-13 5 views
2

В слайде # 6 (http://ejohn.org/apps/learn/#6) «Усовершенствованный Javascript» Джона Ресига показано, что вы можете использовать функцию до ее определения. Вот код:Использование функции javascript перед ее определением

var canFly = function(){ return true; }; 
window.isDeadly = function(){ return true; }; 
assert(isNimble() && canFly() && isDeadly(), "Still works, even though isNimble is moved."); 
function isNimble(){ return true; } 

Однако, я заметил, что следующий код не проходит тест.

assert(canFly(), "Still works, even though isNimble is moved."); 
var canFly = function(){ return true; }; 

Похоже, присвоение анонимной функции переменной отличается от определения именованной функции. Почему это? И как называется эта концепция, которая описывает способность использовать функцию перед ее определением на языке?

+0

Возможный дубликат [JavaScript «hoisting»] (http://stackoverflow.com/questions/15311158/javascript-hoisting) –

+0

Поисковый запрос «JavaScript hoisting» - проверьте связанный дубликат (с немного другим кодом, но хорошие ссылки) - переменные видны для всей функции (путь до 'var'), но получат значение только при первом назначении. –

+0

@AlexeiLevenkov Не лучший ли ответ, скорее, вопрос о сфере действия, а не о порядке вещей? –

ответ

3

объявления функции:

function isNimble(){ return true; } 

определяется, когда код обрабатывается (т.е. до того, как код выполняется), wherease функции выражение:

var canFly = function(){ return true; }; 

оцениваются, когда код запущен, поэтому функция не может быть вызвана до тех пор, пока эта строка не будет выполнена. Вот в чем разница, приводящая к неудаче второго примера.

2

Когда Javascript создает контекст выполнения, он сначала создает все переменные, функции и аргументы. Затем он присваивает им значения. Поскольку isNimble - глобально определенная функция, она создается на первом этапе вместе с canFly, однако canFly не назначается этой функции до тех пор, пока не произойдет второй этап при назначении. Назначение не выполняется до выполнения оператора assert.

См: http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

Вот отрывок из приведенной выше ссылке, которая объясняет это хорошо:

Контекст выполнения в деталях

Итак, мы теперь знаем, что каждый раз, когда функция вызывается, создается новое исполнение . Тем не менее, внутри интерпретатора JavaScript, каждый вызова контекста исполнения имеет 2 этапа:

Creation Stage [when the function is called, but before it executes any code inside]: 
    Create variables, functions and arguments. 
    Create the Scope Chain. 
    Determine the value of "this". 
Activation/Code Execution Stage: 
    Assign values, references to functions and interpret/execute code. 
+0

«Так как' isNimble' является глобально определенной функцией "должно быть" Так как 'isNimble' определяется с помощью * функции декларации *". – RobG

+0

В приведенном тексте обратите внимание, что [при вводе функционального кода] (http://ecma-international.org/ecma-262/5.1/#sec-10.4.3) сначала устанавливается значение * ThisBinding *, а не последнее. – RobG

0

Вот ответ, почему это происходит (и должно произойти). Это не сильно зависит от языка, и я просто надеюсь, что я не использовал странную терминологию для javascript.

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

Когда вы вызываете переменную, вы хотите иметь значение этой переменной в то время, когда вы ее вызываете. Если вы не указали эту переменную до ее вызова, она не должна работать. В частности, это позволяет вам назначать разные функции для одной и той же переменной в разных точках кода.


Так сделать вывод: не путайте «после» с «ниже» и просто рассмотреть простые функции определения произойти до присвоения переменных (даже если назначить функцию этой переменной).

+0

На самом деле это зависит от языка - и JavaScript перемещает все объявления в начало области (подъем). Некоторые языки выдают ошибку, если использовать переменную/функцию перед объявлением ... –

Смежные вопросы