前端面试题 - 2. 什么是闭包,闭包有什么用?

294 阅读1分钟

基础概念

闭包是:能够读取其他函数内部变量的函数。简单理解就是函数中嵌套函数

闭包的作用:

  1. 延长局部变量的生命周期。
  2. 可以在函数外部访问函数的内部变量。

为什么会产生闭包?

  1. 一般函数执行之后内部的变量便会销毁,但是内部函数的作用域链引用了这个变量(外部函数的执行上下文Active Object)。因此这个变量不会销毁。从而形成了闭包。

闭包的缺点:

  1. 内存占用越来越高。所以一些dom对象用完最好销毁掉。

闭包的作用:

  1. 模块化代码避免全局变量的污染。
  2. 变量私有化,并且可以外部增删查改。

一个简单的闭包

/**
 * 一个简单的闭包函数
 * @returns 
 */
function outer() {
  var a = 1

  function inner() {
    console.log(a)    //1
  }
  return inner
}

outer()();

题目1:for 循环和闭包

以下代码输出什么结果?

function createFunc() {
  var result = new Array()


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


// case01 - 作用域链
var result = createFunc()
result[0]() //10
result[1]() //10
result[2]() //10
result[3]() //10
result[4]() //10
result[5]() //10
result[6]() //10
result[7]() //10

解读:

每次创建的函数都先从自己查找,如果没有就从上一层找,直到全局对象。

每个result[i]使用的i不在自己的作用域中,向上查找走到createFunc的作用域找到i。由于for循环每次创建的函数引用i的都是createFunc作用域的。因此循环10次后,createFunc作用域的i变成了10。这个时候子函数输出的i值便都是10.

问题延伸:解决方案

  1. 再包一层闭包
result[i] = (function(i) {
    return function timer() {
      console.log(i);
    }
})(i);
  1. 使用let将变量作用域下降。

参考资料:

  1. 一些题:juejin.cn/post/691147…
  2. 引用关系图解:blog.csdn.net/weixin_4745…
  3. 闭包的优缺点:blog.csdn.net/weixin_5228…