2015-05-06 8 views
2

Может кто-нибудь, пожалуйста, объясните мне, что происходит в следующих трех примерах? Мои мысли для первого примера, bar не выполняется (это просто объявление функции), поэтому, когда выполняется foo, вывод undefined? Для второго примера выполняется bar, так что возвращается значение 3. Для третьего примера я понятия не имею, почему он производит 8.Может кто-нибудь объяснить эти определения функций и подъем?

// 1) 
function foo() { 
    function bar() { 
     return 3; 
    } 
} 
foo(); // undefined 

// 2) 
function foo() { 
    function bar() { 
     return 3; 
    } 
    return bar(); 
} 
foo(); // 3 

// 3) 
function foo(){ 
    function bar(){ 
     return 3; 
    } 
    return bar(); 
    function bar() { 
     return 8; 
    } 
} 
foo(); // 8 
+0

'bar()' дважды объявляется в третьем примере. Поскольку второй объявлен последним, он возвращает 8. – ElGavilan

+0

1) В первом случае, если вы вызываете foo(), выполняется foo(), и теперь доступен bar(). Но для того, чтобы выполнить бар, вам нужно явно его называть. 2) во втором случае вы вызываете foo(), а в панели foo() доступны, и вы вызываете bar(), записывая return bar(); 3) В третьем случае см. Объяснение во втором случае. Для получения дополнительной информации см. Это: http://stackoverflow.com/questions/7295634/javascript-nested-function –

+0

как вызвать бар явно? – DaeYoung

ответ

3

Вы правильно о примерах 1 и 2, так что я буду просто обратиться пример 3.

В то время как это выглядит, как вы вызываете bar() прежде чем переопределить его, function заявления рассматриваются специально. Все функции определены, когда область ввода сначала вводится, они не выполняются по порядку. Если у вас несколько объявлений для одной и той же функции, последняя эффективна. Таким образом, нет никакой разницы между:

function bar() { 
    // version 1 
} 
return bar(); 
function bar() { 
    // version 2 
} 

и:

function bar() { 
    // version 2 
} 
return bar(); 

Это так, что функция объявления отличается от присваивания выражение функции переменной. Если бы вы вместо этого написал:

function foo() { 
    var bar = function() { 
     return 3; 
    } 
    return bar(); 
    var bar = function() { 
     return 8; 
    } 
} 
foo(); 

то вернулся бы 3.

+0

Это ИМО лучший ответ, потому что он упоминает синтаксис var x = function и когда объявления функций выполняются. –

0

Ваши предположения относительно первых двух примеров являются правильными.

Последний пример возвращает 8, потому что bar переопределяется до того, как вызывается foo. Вот основной график событий:

  1. foo определяется

    • bar определяется как функция, которая возвращает 3
    • bar переопределена как функция, которая возвращает 8
  2. foo
    • return заявления ударили и переопределены bar функции выполняются, возвращая 8
0

В вашем третьем примере bar() дважды объявлено. Объявление, которое возвращает 8, объявляется последним, поэтому оно переопределяет bar() и является объявлением, которое выполняется.

function foo(){ 
    function bar(){ // first declaration of bar() 
     return 3; 
    } 

    return bar(); // this executes the code in bar() as it was most recently redefined 

    function bar() { // second and last declaration of bar(); this redefines the 
        // first declaration 
     return 8; 
    } 
} 
foo(); // 8 
0

Если функция с таким же именем и областью объявлена ​​дважды, она будет игнорировать первую и выполнить вторую функцию. Это то, что происходит, это №3.

+0

поэтому строка возврата() вызывается после функции bar() {return 8; } объявление? – DaeYoung

+0

@DaeYoung Youe 'return bar()' statement - это то, что вызывает метод, объявленный как 'function bar() {return 8; } ' – ElGavilan

+0

Когда выполняется javascript, для' var bar = function() 'будет выполняться подъем. Это означает, что он будет перенесен в верхнюю часть области действия, так как это объявление переменной, а затем будут выполняться функции, которые используют/управляют этими данными (в данном случае оператор 'return'). Google javascript hoisting для получения дополнительной информации по этой теме –

2

Настоящий ответ, который вы ищете, - Подъемник.

В вашем третьем примере, что на самом деле выполняется интерпретатором Javascript является:

var foo = function() { 
    var bar = function() { 
    return 3; 
    } 
    var bar = function() { 
    return 8; 
    } 
    return bar(); 
} 

foo(); // 8 

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

http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

+0

Теперь я ясно вижу, что происходит. Благодаря! – DaeYoung

0

Когда следующий выполняются обе функция декларации поднимается к верхней части IIFE Области применения - вторая декларация переопределяет первую.

(function IIFE(){ 
    function bar(){ 
     return 3; 
    } 
    return bar(); 
    function bar() { 
     return 8; 
    } 
})() 

(function IIFE(){ 
    function bar(){ 
     return 3; 
    } 
    function bar() { 
     return 8; 
    } 
    return bar(); 
})() 

(function IIFE(){ 
    function bar() { 
     return 8; 
    } 
    return bar(); 
})()