闭包就是能够读取其他函数内部变量的函数,也就是指有权访问另一个函数作用域中变量的函数
创建闭包的最常见方式就是在一个函数内创建另一个函数,通过另外一个函数的访问这个函数的局部变量,利用闭包突破作用域链
闭包的特点
1. 函数内再嵌套函数
2. 内部函数可以引用外层的参数和变量
3. 参数和变量不会被垃圾回收机制回收
说说你对闭包的理解
闭包就是一个嵌套函数,一般来说,内部函数能够访问上一级乃至全局的变量,通过闭包可以实现外部访问函数局部内的变量。如果我们把作用域简单的分级的话,假设全局作用域是第一级,其中定义的函数体内的作用域为第二级,在第二级作用域内嵌套定义函数体的内部作用域为第三级。传统意义上,第一级不能访问第二级的变量,第二级不能访问第三级的变量,这种变量叫做局部变量,而反过来可以,这个就叫做作用域链。闭包这种机制,可以在第一级作用域中通过第三级作用域引用到第二级作用域中的变量。方法就是在第二级作用域中向第一级作用域返回拥有第三级作用域的函数引用。这个引用才是关键,因为这个引用的存在,相关的第三级作用域与第二级作用域都成了这个引用的上下文,迫使垃圾回收机制GC不能回收这个链上所占用的资源,而如果没有这个引用,则跟一般函数一样,函数运行完,资源就会被回收。
例如:
function a (){
var **i= **0;
function b(){
alert(++i)
}
return b
}
var c = a()
c()
c()
c()
闭包的作用就是 a 执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会回收a所占用的资源,因为a内部的函数b执行,需要依赖a中的变量。由于闭包的存在,使得函数a返回后,a中的i始终存在,这样每次执行c(),i都会自动+1,那么,如果a不返回b,情况就不一样了。因为a执行后,b没有被返回给a的外界,只是被a引用了,因此,a也只会被b引用,函数a和b互相引用但又不被外界打扰,函数a和b就会被GC回收。
实际上,闭包延长变量的生命周期,通常函数的作用域即变量会在函数执行结束后被销毁,但当函数返回一个闭包,只要闭包不被释放,整条作用域链都会被占用内存,(闭包延长变量的生命周期,只的是被第一级引用的情况)
作用域链即函数自己的作用域,上一层函数的作用域...直到全局作用域,访问一个变量时,自己没有就一层一层网上找,直到全局,若还没有就会报错 *** is not defined
使用闭包主要是为了设置私有的变量和方法
优点:可以避免全局变量的污染。
缺点:常驻内存,会增大内存的使用量。使用不当很容易造成内存泄漏
解决方法:在退出函数之前,将不使用的局部变量删除
闭包应用场景:
设置私有变量和方法,让这些变量的值始终保存在内存中,还有读取函数的内部变量。
为什么会出现闭包,解决了什么问题
受Javascript链式作用域的影响,父级无法访问到子级变量的值,为了解决这个问题,才使用了闭包的概念;
哪些操作会造成内存泄漏
内存泄漏指任何对象,在你不再拥有或需要他之后,依然存在
1. setTimeout 第一个参数使用空字符串,而非函数
2. 闭包使用不当
3. 控制台日志
4. 循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)