likes
comments
collection
share

面试常考:聊一聊闭包

作者站长头像
站长
· 阅读数 28

前言

闭包(Closure)是 JavaScript 中一个非常重要的概念,它允许一个函数访问并操作其外部作用域中的变量,即使在该函数被外部作用域之外的地方调用时也是如此。

闭包是JS面试的一大考点,也是一大难点,今天就来聊一聊闭包,将闭包的知识点吃透。

正文

作用域链

看到下面这段代码,你知道打印结果是什么吗?知道打印结果是Jerry,那你知道原因吗?

function bar() {
    console.log(myName); // 打印结果为 Jerry
}

function foo () {
    var myName = 'Tom'
    bar()
}
var myName = 'Jerry'
foo()

在作用域链中,outer 指向的是外部(上一级)执行上下文的作用域,像 bar 函数声明在了全局,那bar 的 outer 就指向全局。如下图所示,bar 函数 的执行会先在 bar 的执行上下文里面找 myName,找不到就会顺着作用域链查找,就在全局作用域中找到了 myName 的值为 Jerry。

面试常考:聊一聊闭包

作用域链并不是在调用栈中从上到下查找,而是看当前执行上下文变量环境中的outer指向来定,而outer指向的规则是,我的词法作用域在哪里,outer就指向哪里。

词法作用域

词法作用域由函数声明的位置来决定,跟函数在哪里调用没有关系,如下图所示。

面试常考:聊一聊闭包

块级作用域

let和{}形成块级作用域

如下面这段代码展示,打印结果是 10 个 10,和我们预期的结果为 0-9 不一样,这是因为 i 是在全局声明的,执行结果时 i 的值已经为 10 了。

var arr = []

for (var i = 0; i < 10; i++) {
  arr[i] = function() {
    console.log(i);
  }
}

for (var j = 0; j < arr.length; j++) {
  arr[j]()
}

如果将 var i 改为 let i ,那么得到的结果就是 0-9 ,这是因为 let 和 {} 形成块级作用域,每循环一次就会形成一个块级作用域,最后 outer 会指向块级作用域,因此打印结果为 0-9。

面试常考:聊一聊闭包

闭包

在javaScript中,根据词法作用域的规则,内部函数一定能访问外部函数中的变量,当内部函数被拿到外部函数之外调用时,即使外部函数执行完毕,但是内部函数对外部函数中的变量依然存在引用,那么这些被引用的变量会以一个集合的方式保存下来,这个集合就是闭包

在下面这个例子中,内部函数是 bar,外部函数是 foo,bar函数在foo函数外面被调用,foo函数执行完毕,但是bar引用了foo中的 myName,那么这个被引用的变量 myName 就被保存下来形成了闭包。

function foo() {

  function bar() {
    var age = 18
    console.log(myName);// 打印结果为 'Tom'
  }
  var myName = 'Tom'
  
    return bar
}
var myName = 'Jerry'
var fn = foo()
fn()

上面这段代码会先预编译,先形成一个全局执行上下文,接着调用foo函数,形成了foo执行上下文,foo返回出来了bar,已经完成了foo的使命了,这时候就会回收foo,但是又因为bar被调用了,还用到了foo中的变量,这时候就会回收除了 myName 的其他东西,而 myName 就被存放在了闭包里面。 面试常考:聊一聊闭包 如上图所示,最后bar的outer会指向foo,打印结果为 Tom

闭包的运用

闭包的作用:实现变量私有化

用代码实现一个累加器,这时候可以运用到闭包,如下所示,函数add返回了fn,add执行上下文留下了闭包,闭包中的变量count会保留到下一次调用。

function add() {
    let count = 0
    function fn() {
      count++
      return count
    }
    return fn
  }
  var res = add()
  
  console.log(res());  // 1
  console.log(res());   // 2
  console.log(res());   // 3

面试常考:聊一聊闭包

结语

在实际开发过程中,合理地使用闭包能够提升代码的质量,但也需要注意避免不当使用导致内存泄漏等问题。希望本文能帮助你更好地理解和应用闭包这一概念。

面试常考:聊一聊闭包

转载自:https://juejin.cn/post/7397019920322052123
评论
请登录