有人可以解释这些功能定义和提升吗?

Can someone explain these function definitions and hoisting?

有人可以向我解释以下三个示例中发生了什么吗? 我的想法是第一个例子,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

您对前两个示例的假设是正确的。

最后一个例子 returns 8 因为 bar 在调用 foo 之前被重新定义。这是事件的基本时间表:

  1. foo定义

    • bar 定义为 returns 3
    • 的函数
    • bar 被重新定义为 returns 8
    • 的函数
  2. foo 被调用
    • 命中 return 语句并执行重新定义的 bar 函数,返回 8

在您的第三个示例中,bar() 被声明了两次。 returns8最后声明的声明,所以重新定义了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

如果同名同作用域的函数被声明了两次,它将忽略第一个并执行第二个函数。这就是正在发生的事情#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

您正在寻找的真正答案是 提升

在你的第三个例子中,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

当执行以下语句时,两个函数声明都被提升到 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();
})()