目录
如何产生闭包?
当一个嵌套的内部函数引用了嵌套的外部函数的变量时,就产生了闭包
产生闭包的条件?
- 函数嵌套
- 内部函数引用了外部函数的数据(变量/函数)
- 且执行外部函数
核心知识点:
内嵌函数
对象被引用时不释放对象(垃圾回收机制)
函数嵌套(内嵌函数):
在JavaScript中所有函数都能访问它们上一层的作用域。JavaScript支持嵌套函数,嵌套函数可以访问上一层的函数变量
JavaScript的垃圾回收机制
在JavaScript中,如果一个 对象不在被引用,那么这个对象就会被CG回收,如果两个对象互相引用,而不再被其他所引用,那么这两个互相引用的对象就会被回收,如果函数a被b引用,b又被a外的c引用,那么函数a执行后不会被回收,因为有被引用
什么是闭包?
- 闭包是嵌套的内部函数
- 包含被引用变量(函数)的对象
function fn1(){
var a=2
function fn2(){
a++
console.log(a)
}
reture fn2//函数也能返回,函数也是数据
}
var f=fn1() //外部函数引用
f()//3
f()//4 相当于执行fn1()(),执行的谁fn2里面的代码,这个不执行var a=2这个代码
//产生了一次闭包
fn1()
//产生了两次闭包
- 外部函数调用几次,会产生几次闭包
- 执行在var a=2时,函数定义早已经执行过了,说明闭包已经产生(执行函数定义就会产生闭包(不用调用内部函数)
闭包的作用
- 使用函数内部的变量在函数执行完后,任然存活在内存中(延长了局部变量的声明周期)
- 让函数外部可以操作(读写)到函数内部的数据(变量/函数)
例如:有人引用外部局部变量(a),所以他(a)仍然存活在内存中,fn2执行完就被释放了(需要用reture操作)
f只要引用了其中的局部变量或函数,就不会被释放,就不是垃圾对象,如果没有引用,就会被释放
闭包的生命周期
产生:在嵌套内部函数定义执行完时就产生了,不是在调用的时候,上图在var a=2的时候就产生了,如果下面没有var的话
消失:在嵌套的内部函数成为垃圾对象时(f=null)
应用:定义JS模块
- 具有特定功能的JS文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外暴露一个包,要用n个方法/函数放到一个对象里面
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
返回多个函数怎么办?
- 放到一个对象里面
- 直接将两个函数给了window对象,就可以直接在外面引用直接用,需要用return回去的话,需要实例化
缺点:
函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
容易造成内存泄漏
解决
能不用闭包就不用‘
及时释放
小知识点:
内存溢出(满了还存)
内存泄漏(占用的内存没有及时释放,本来我有很大的内存可用,但是被泄漏了,内存泄漏积累多了就容易导致内存溢出)
例如:闭包,没有及时清除的计时器或回调函数,意外的全局变量