MST
星途 面试题库

面试题:JavaScript 闭包在复杂函数作用域嵌套下的行为分析

假设有如下代码:function outer() { let a = 1; function middle() { let b = 2; function inner() { return a + b; } return inner; } return middle; } let func = outer()(); 请详细说明这里面涉及的函数作用域链以及闭包的工作原理,特别是每次函数调用时作用域的变化。
28.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
  1. 函数作用域链

    • outer函数
      • outer函数创建了自己的作用域。在这个作用域中,定义了变量a并赋值为1
      • outer函数执行时,它的作用域链首先包含自身的作用域,其中有变量a
    • middle函数
      • middle函数定义在outer函数内部,它的作用域链由两部分组成。
      • 首先是middle函数自身的作用域,其中定义了变量b并赋值为2
      • 然后是它的外部作用域,也就是outer函数的作用域。所以middle函数可以访问outer函数作用域中的变量a
    • inner函数
      • inner函数定义在middle函数内部,它的作用域链由三部分组成。
      • 首先是inner函数自身的作用域(在这个例子中,它没有定义新的变量)。
      • 然后是它的直接外部作用域,即middle函数的作用域,在这里可以访问变量b
      • 最后是middle函数的外部作用域,也就是outer函数的作用域,在这里可以访问变量a
  2. 闭包的工作原理

    • 闭包是指一个函数能够访问并记住其词法作用域,即使该函数在其原始作用域之外被调用。
    • 在这段代码中,inner函数形成了闭包。当inner函数被返回并在outer函数外部调用时,它仍然能够访问outer函数作用域中的amiddle函数作用域中的b
    • 这是因为inner函数在创建时,它的作用域链被固定下来,包含了middle函数和outer函数的作用域。即使outermiddle函数已经执行完毕,它们的作用域因为被inner函数引用(闭包)而不会被垃圾回收机制回收。
  3. 每次函数调用时作用域的变化

    • outer函数调用
      • outer函数被调用时,outer函数的作用域被创建,变量a被初始化。此时作用域链只有outer函数自身的作用域。
      • outer函数返回middle函数,outer函数执行完毕,但由于middle函数对outer函数作用域的引用(通过闭包),outer函数的作用域不会被销毁。
    • middle函数调用
      • middle函数被调用(通过outer()()),middle函数的作用域被创建,变量b被初始化。
      • middle函数的作用域链包含自身作用域和outer函数的作用域。
      • middle函数返回inner函数,middle函数执行完毕,但由于inner函数对middle函数作用域的引用(通过闭包),middle函数的作用域不会被销毁。
    • inner函数调用
      • inner函数被调用,inner函数的作用域被创建。
      • inner函数的作用域链包含自身作用域、middle函数的作用域和outer函数的作用域。
      • inner函数执行return a + b,从作用域链中找到ab,计算并返回结果3inner函数执行完毕,由于没有其他地方引用inner函数,inner函数自身的作用域被销毁,但middleouter函数的作用域因为闭包的存在仍然保留。