【问题标题】:Can someone explain these function definitions and hoisting?有人可以解释这些函数定义和提升吗?
【发布时间】:2015-05-06 19:20:26
【问题描述】:

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

【问题讨论】:

  • bar() 在第三个示例中被声明了两次。由于第二个是最后声明的,因此它返回 8。
  • 1) 在第一种情况下,如果您调用 foo(),则会执行 foo(),并且 bar() 现在可用。但为了执行该栏,您需要显式调用它。 2)在第二种情况下,您正在调用 foo(),并且在 foo() 中 bar 可用,并且您通过编写 return bar() 来调用 bar(); 3) 第三种情况,见第二种情况的解释。有关更多信息,请参阅:stackoverflow.com/questions/7295634/javascript-nested-function
  • 如何显式调用bar?
  • @DaeYoung return bar();
  • @DaeYoung 我的意思是,在第一种情况下,当你调用 foo() 时,bar() 是可用的,但你没有调用 bar() 函数,尽管它是可用的。

标签: javascript hoisting


【解决方案1】:

您对示例 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

【讨论】:

  • 这是 IMO 的最佳答案,因为它提到了 var x = 函数语法以及何时执行函数声明。
【解决方案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

【讨论】:

    【解决方案3】:

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

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

    1. foo 已定义

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 所以在函数 bar(){ return 8; 之后调用 return bar() } 声明?
      • @DaeYoung Youe return bar() 声明是调用声明为function bar(){ return 8; }的方法
      • 执行javascript时,var bar = function()会发生提升。这意味着它将被带到范围的顶部,因为它是一个变量声明,然后将运行使用/操作该数据的函数(在本例中为 return 语句)。 Google javascript 提升以了解有关该主题的更多信息
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2010-10-28
          • 2020-06-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-27
          • 2020-02-23
          • 2021-12-06
          • 1970-01-01
          相关资源
          最近更新 更多