2015-07-10 2 views
5

Я вообще не javascript noob, хотя за всю свою жизнь я никогда не сталкивался с этим, но правильно ли я предполагаю, что javascript должен назначать функции перед запуском чего-либо или чего-то еще?Определены ли функции независимо от заказа?

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

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 
alert(typeof bar()); 

Может ли кто-нибудь объяснить это для меня?

+0

Возможный дубликат функции [Javascript function scoping and hoisting] (http://stackoverflow.com/questions/7506844/javascript-function-scoping-and-hoisting) – DTing

+0

Да. При вводе контекста [* execute *] (http://ecma-international.org/ecma-262/6.0/index.html#sec-execution-contexts) все объявления функций и переменных обрабатываются до запуска любого кода. – RobG

ответ

7

Это поведение JavaScript называется Подъемник. Существует хорошее объяснение на MDN (https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)

В JavaScript возведены функции и переменные. Подъем - это поведение JavaScript для перемещения объявлений в верхней части области (глобальная область видимости или область текущей функции).

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

В принципе, если вы объявляете переменную как это:

console.log(s);    // s === undefined 
var s = 'some string'; 

s декларация будет «водрузил» к началу объема (т.е. там не будет никаких ReferenceError на линии с console.log). Значение переменной в этот момент не будет определено, хотя.

То же самое происходит с назначением анонимной функции переменным, так:

console.log(f);    // f === undefined 
f();      // TypeError: f is not a function 
var f = function() {};  // assigning an anonymous function as a value 
f();      // ok, now it is a function ;) 

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

С другой стороны, если вы объявляете с именем функции:

console.log(f);    // f === function f() 
f();      // we can already run it 
function f() {};   // named function declaration 

Это определение также будет поднят, так что вы можете запустить его даже в первой строке рамки вы объявили его.

+0

Мне действительно не нравится термин «подъем», это неправильное название, и приведенное объяснение плохое. Это означает, что код каким-то образом перемещен, это не так. Реальный ответ заключается в том, что объявления функций и переменных * обрабатываются * перед выполнением любого кода. – RobG

+0

Блестяще объяснил, спасибо, так много, это ясно, я даже не знал, что javascript сделал это с вложенными функциями, я думал, что это только корневая область. Silly me –

+0

@RobG Да, справедливая точка. Это немного похоже на то, что мы имели с «функциями, вызывающими вызов» на некоторое время, не так ли? Я также не поклонник (вы должны услышать, как он переводится на мой язык, это больше похоже на «возвышение»;)). Это довольно принятый термин, и я думаю, что его легче объяснить, не вдаваясь в подробности (даже если жертвовать точностью немного) –

0

Ну, в функции JavaScript нет ничего, кроме объекта.

Когда вы говорите TypeOf бар(), в функции бар вы возвращаете Foo, который является еще одним function.You просто возвращается имя функции, так, он возвращает конструктор обув function.So, ваш typeof получить значение foo constructor который является типом функции. Так, это функция предупреждения.Он по-прежнему относятся к Foo из closure

Снова в бар Defination, Вы возвращаетесь Foo, но его определение еще не encountered.In JavaScript, когда при разборе инструкции, декларации переменной и функция находится сверху в области текущей функции.

Итак, ваше заявление

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 

эквивалентно

function bar() { 
    function foo() {} 
    return foo; 
    foo = 10; 

    var foo = '11'; 

Это называется JavaScript top hoist

} 
0

Это довольно легко проверить;

foo(1); 

function foo(i) { 
    if (bar()) { 
     alert("foo called, bar true, i = " + i); 
    }; 
} 

foo(2); 

function bar() { 
    return true; 
} 

foo(3); 

DEMO

Это показывает, что Javascript загружает все функции перед выполнением ничего. Поэтому не имеет значения, какие функции порядка определены.

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