闭包是什么?

一、闭包的概念理解

闭包是指 有权访问另一个函数作用域中的变量函数,或着,可以简单理解为定义在一个函数内部的函数,内部函数可以访问到外部函数的局部变量。

例如,函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。

function A() {
  let a = 1
  window.B = function () {
      console.log(a)
  }
}
B()  // 1
二、闭包存在的意义

在 JS 中,闭包存在的意义简单理解就是让我们可以间接访问函数内部的变量,延长变量的使用寿命以及减少命名空间的污染。

三、闭包的三大特性
  • 函数嵌套函数
  • 函数内部可以引用外部的参数及变量
  • 参数和变量不会被垃圾回收机制回收
四、闭包的优缺点

优势

  • 可创建私有变量

通过使用闭包,可以在外部调用闭包函数,从而在函数外部能够间接访问到函数内部的变量,也可以使用这种方法来创建私有变量避免全局变量的污染。

  • 让这些变量的值始终保持在内存中

使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被垃圾回收机制回收实现变量数据共享。

缺点

  • 滥用闭包会导致大量变量不会被垃圾回收机制回收,内存消耗很大,可能会造成网页卡顿等性能问题
  • 函数内部的局部变量没有被释放,使得占用内存时间会变长,容易造成内存泄漏。
  • 闭包会在父函数外部,改变父函数内部变量的值。若将函数当作Object使用,把闭包当作它的共用方法,内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。

解决方案

注意编码习惯,在退出函数之前,将不使用的局部变量及时释放。

function fn1(){
    var arr = new Array[100000]
    function fn2(){
        console.log(arr.length)
    }
    return fn2
}
var f = fn1()
f()

案例分析: 函数执行后在创建了10万长度的数组存储在内存中,我们在调用后并没有对函数进行手动释放造成了内存的浪费

解决办法:

var f = fn1()
f()
f = null //让内部函数成为垃圾对象,从而回收闭包 
五、闭包的经典应用

问题

循环中使用闭包解决 var 定义函数的问题。

for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

问题分析:因为 setTimeout 是个异步函数,所以会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆6。

解决方法

1、使用闭包的方式

for (var i = 1; i <= 5; i++) { 
(function(j) {
  setTimeout(
    function timer() {
       console.log(j)
    }, j * 1000)
 }
)(i);
}

分析:

  • 首先使用了立即执行函数将 i 传入函数内部,
  • 这个时候值就被固定在了参数 j 上面不会改变,
  • 当下次执行 timer 这个闭包的时候,
  • 就可以使用外部函数的变量 j,从而达到目的。

2、使用 setTimeout 的第三个参数

for (var i = 1; i <= 5; i++) {
  setTimeout(
    function timer(j) {
      console.log(j)
    }, i * 1000,  i
  )
}

分析:

  • 这个参数会被当成 timer 函数的参数传入。
  • 通过setTimeout的API解决,每次执行时,都传入参数i,并通过形参形成闭包

3、使用 let 定义 i

这个是最为推荐的方式

for (let i = 1; i <= 5; i++) {
  setTimeout(
   function timer() {
     console.log(i)
   }, i * 1000
  )
}
  • 通过ES6的let关键字,管理i的作用域,每次观察i时都是观察的定时器启动时i的数值
  • 通过块级作用域形成闭包

相关文章  👉面试官:说说你对闭包的理解?闭包使用场景

  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值