闭包:闭包理解 常见的闭包 闭包的作用 闭包的生命周期 (闭包应用:定义JS模块) 闭包的缺点 内存溢出与内存泄漏 测试题 循环遍历加监听

闭包理解

1.闭包的产生

当一个嵌套的内部函数(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。

2.闭包到底是什么?

廖雪峰:闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。
理解一(大部分人的理解):闭包是嵌套的内部函数
理解二(少部分人的理解):包含被引用变量(函数)的那个对象(这个对象存在于嵌套的内部函数中)
可以使用开发者工具来调试查看。

3.产生闭包的条件?

(1)存在函数嵌套
(2)嵌套的内部函数必须引用在外部函数中定义的变量(函数)
(3)外部函数被执行(内部的函数不用执行,只需要执行其函数定义就已经产生闭包)

4.产生了几个闭包

闭包被创建了几个,就是外部函数被执行了几次,产生了几个内部函数对象,因为闭包就是内部函数,只有执行外部函数才会去创建内部函数,和内部函数被执行几次没有关系。

常见的闭包

1.将函数作为另一个函数的返回值

2.将函数作为实参传递给另一个函数调用

闭包的作用

1.闭包所使用的函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)
2.让函数外部可以操作(读写)到函数内部的数据(变量/函数)

问题:

1.函数执行完后,函数内部声明的局部变量是否还存在?
一般是不存在的,存在于闭包中的变量才可能存在
2.在函数外部能直接访问函数内部的局部变量吗?
不能,但是如果有包含这个局部变量的闭包,我们就可以通过闭包让外部操作它

代码理解

1.这是上面常见的闭包中的1中的代码
2.执行fn1将会产生两个闭包,fn2和fn3
3.第23行如果只有fn1(),是会产生两个闭包,但产生完就没了,因为fn2和fn3是局部变量
4.第23行用f保存了fn3函数对象的引用,fn3变量是消失了,但它所指向的这个函数还存在于f中,所以这个闭包还存在
5.第24行代码并不是说执行了fn3,fn3早没了,执行的是f,f函数和fn3一样而已
6.就是因为4中所说的这个闭包的存在,第24行执行结果才会是1,因为fn1的变量a被保存在这个闭包中,也就体现了闭包的作用中的1(访问到了a),2(a--,操作了a),也体现了问题中的1(a还存在),2(操作了a)

闭包的生命周期

1.产生

在嵌套内部函数定义执行完就产生了(不是在调用时)

2.死亡

在嵌套的内部函数成为垃圾对象时

闭包应用:定义JS模块

JS模块

具有特定功能的js文件(特定功能:有些函数,操作一些数据)
将所有的数据和功能都封装在一个函数内部 (私有的) (要想私有必须放到一个函数中,对象的属性是直接可见的)
只向外暴露一个包含n个方法的对象或函数
模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能

代码1

 

代码2

 

 代码1使用先要执行函数,代码2使用起来,更直接更方便 

闭包的缺点

1.缺点

函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
容易造成内存泄露

2.解决

能不用闭包就不用闭包
及时释放

内存溢出与内存泄漏

1.内存溢出

一种程序运行出现的错误
当程序运行需要的内存超过了剩余的内存时,就抛出内存溢出的错误

2.内存泄漏

占用的内存没有及时释放
内存泄漏积累多了就容易导致内存溢出
常见的内存泄漏:
  意外的全局变量(在函数内部定义的全局变量,以为是局部变量)
  没有及时清理的计时器或回调函数
  闭包(没有及时释放,导致一直占用内存)

测试题

测试题1

测试题2

测试题3

循环遍历加监听

点击三个按钮分别显示它是第几个

1.普通实现

2.利用闭包实现(闭包不释放是因为闭包被按钮对象中的onclick属性引用,按钮对象是全局变量,在窗口未关闭之前不会被释放  )

学识浅薄,如有错误,恳请斧正,在下不胜感激。

原文地址:https://www.cnblogs.com/yin-jie/p/14752856.html