Может кто-нибудь объяснить эти определения функций и подъема?

Может кто-нибудь объяснить мне, что происходит в следующих трех примерах? Мои мысли для первого примера, 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

6 ответов

Решение

Вы правы насчет примеров 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,

Реальный ответ, который вы ищете, - подъем.

В третьем примере интерпретатор 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

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

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

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

  1. foo определено

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

Когда выполняется следующее, оба объявления функций поднимаются в верхнюю часть 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();
})()

В вашем третьем примере 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
Другие вопросы по тегам