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
4

6 回答 6

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

于 2015-05-06T19:28:23.547 回答
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

于 2015-05-06T19:32:42.890 回答
0

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

最后一个示例返回8,因为在调用bar之前被重新定义foo。以下是事件的基本时间表:

  1. foo被定义为

    • bar被定义为返回的函数3
    • bar被重新定义为返回的函数8
  2. foo被调用
    • return语句被命中并执行重新定义的函数bar,返回8
于 2015-05-06T19:24:10.550 回答
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
于 2015-05-06T19:24:55.627 回答
0

如果同名和作用域的函数被声明两次,它将忽略第一个函数并执行第二个函数。这就是正在发生的是#3。

于 2015-05-06T19:25:05.383 回答
0

When the following is executed both function declarations are hoisted to the top of the IIFE scope - the second declaration overriding the first.

(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();
})()
于 2015-05-06T19:40:00.627 回答