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

时间:2015-05-06 19:20:26

标签: javascript 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

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:0)

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

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

  1. foo已定义

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

答案 3 :(得分: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

答案 4 :(得分:0)

如果声明了具有相同名称和范围的函数两次,它将忽略第一个函数并执行第二个函数。这就是#3。

答案 5 :(得分:0)

当执行以下操作时,两个函数声明都被提升到@”H:|-20-[label1]-10-[label2]-15-“范围的顶部 - 第二个声明覆盖第一个。

IIFE