我是靠谱客的博主 顺心棒棒糖,这篇文章主要介绍JavaScript闭包什么是闭包闭包咋来的为啥要用闭包闭包能干啥最后需要要注意!,现在分享给大家,希望可以做个参考。

JavaScript闭包

  • 什么是闭包
  • 闭包咋来的
      • 自己简单总结下
        • 闭包的产生有三个条件
        • 为什么这个函数空间不会被销毁?
          • 什么特殊情况?
          • 什么情况会被销毁?
      • 看一个简单的应用闭包的例子
  • 为啥要用闭包
      • 闭包的优点
      • 闭包的缺点
      • 间接返回一个函数
  • 闭包能干啥
      • 简单使用闭包函数
      • 利用闭包实现单例模式
  • 最后需要要注意!


什么是闭包

MDN的解释是
函数与对其状态即词法环境的引用共同构成闭包。也就是说,闭包可以让你从内部函数访问外部函数作用域。在JavaScript,函数在每次创建时生成闭包。

闭包咋来的

自己简单总结下

  • 闭包的产生有三个条件

    • 要有一个内嵌函数,就是在函数 fn1 内部直接或间接返回了一个函数 fn2

    • fn2 函数内部必须引用着 fn1 函数的变量

    • fn1 函数返回的 fn2 函数要有外部变量接收

      • 形成了一个不会销毁的 fn1 函数的执行空间,我们管这个不会销毁的函数空间叫做 闭包空间
      • 把函数 fn1 里面返回的函数 fn2,叫做函数 fn1 的 闭包函数
  • 为什么这个函数空间不会被销毁?

    一个函数再执行的时候,会开辟一个函数执行空间,代码执行完毕之后,根据 js 垃圾回收机制,这个函数执行空间会被销毁。
    在一个特殊情况下,函数的这个执行空间不会被销毁。
    什么特殊情况?
    当函数内部返回一个复杂数据类型,并且在函数外部有变量接收这个复杂数据类型的时候,这个函数的执行空间就不会被销毁,即不会被垃圾回收机制回收。

垃圾回收机制:
在JavaScript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收;
如果两个对象互相引用,而不再被第三者所引用,那么这两个互相引用的对象也会被回收。

什么情况会被销毁?

当函数外部的变量不再引用函数内部的返回值时会被销毁。

看一个简单的应用闭包的例子

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
function a() { // 这个 num 变量是函数 a 的私有变量 var num = 100 return function b() { console.log(num) } } // res 接受的就是函数 a 内部返回的一个复杂数据类型(函数b),导致函数 a 的执行空间不会销毁 var res = a() res() //打印100 //这样就做到了从函数 A 外部拿到函数 A 的 num

为啥要用闭包

闭包的优点

  1. 延长了变量的生命周期
  2. 可以访问函数内部的私有变量

闭包的缺点

  • 因为一段内存空间内的函数空间不会被销毁,在使用不当的情况下,容易发生内存泄漏 (致命的缺点)
    所以,如果闭包函数此时使用完毕之后,后面不再使用,应该另外部接收闭包函数的参数手动销毁

间接返回一个函数

直接返回一个函数就是 return function() {}
当我们需要访问多个私有数据时,就要用到间接返回的方式

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function fn() { var num = 100 var num2 = 200 return { getNum: function () { console.log(num) }, getNum2: function () { console.log(num2) } } } var res = fn() // res 得到的是一个对象 // 这个对象里面的函数是 fn 的闭包函数 console.log(res) res.getNum() //100 res.getNum2() //200

闭包能干啥

简单使用闭包函数

循环绑定事件

复制代码
1
2
3
4
5
6
7
8
9
10
var btns = document.querySelectorAll('button') function loop(num) { btns[num].onclick = function() { console.log(num) } } for (var i = 0; i < btns.length; i++) { loop(i) }

实际上就是es6用let解决循环绑定事件的本质

复制代码
1
2
3
4
5
6
for (let i = 0; i < btns.length; i++) { btns[i].onclick = function() { console.log(i) } }

利用闭包实现单例模式

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var Person = (function fn() { //匿名自执行函数 function Person() { //真正的构造函数 console.log('hello world') } var instance = null //声明一个instance 对象 return function() { return instance || (instance = new Person()) } //如果存在返回instance,如果不存在则new一个Person对象 })() var p1 = new Person() console.log(p1) var p2 = new Person() console.log(p2) console.log(p1 === p2) //true

最后需要要注意!

因为闭包的缺点就是闭包函数常驻内存会增大内存使用量,而且使用不当很容易造成内存泄漏。
所以如果不是因为特殊情况而必须需要闭包,在没有必要的情况下,不要使用闭包!
闭包:慎用!!



关键字:JavaScript , 闭包 ,函数

最后

以上就是顺心棒棒糖最近收集整理的关于JavaScript闭包什么是闭包闭包咋来的为啥要用闭包闭包能干啥最后需要要注意!的全部内容,更多相关JavaScript闭包什么是闭包闭包咋来内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部