闭包
当一个嵌套的内部函数引用了嵌套外部函数的变量,就产生了闭包。闭包是指有权访问另一个函数作用域中的变量的函数。
如何理解闭包
闭包就是嵌套的内部函数
内部函数中包含被引用的对象
产生闭包的条件
函数的嵌套(不需要调用内部函数)
内部函数引用了外部函数的数据(变量/函数)
fucntion fn1(){
var a = 2
var b = 'abc'
function fn2(){ //执行函数定义就会产生闭包,但是要定义外部函数
console.log(a)
}
fn2()
}
fn1()
常见的闭包
-
将函数作为另一函数的返回值
fucntion fn1(){ var a = 2 function fn2(){ a++ console.log(a) } return fn2 } var f = fn1() f()//3 f()//4
这里的重点就是a是函数级作用域,理论上函数结束a就会被销毁,当变量a变成闭包的时候,a始终保存在内存里,不会随着函数的结束而自动销毁。
-
将函数作为实参传递给另一个函数调用
function showDelay(msg,time){ setTimeout(function(){ alert(msg) },time) } showDelay('zlearn',2000)
闭包的作用
如果没有闭包,函数执行完,局部变量就会释放
如果没有闭包,我们就不能再外部操作变量
- 可以在函数的外部访问到函数内部的局部变量。
- 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。
闭包的生命周期
fucntion fn1(){
//此时闭包已经产生,因为产生了函数提升
var a = 2
function fn2(){
a++
console.log(a)
}
return fn2
}
var f = fn1()
f()//3
f()//4
f = null//闭包死亡(包含闭包的函数对象成为垃圾对象)
自定义js模块
具有特定功能的js文件
接下来我们自定义一个js模块
首先在myModule.js里面写我们要的功能,通过匿名函数立即执行,通过window.myModule向外暴露对象
myModule.js
(function () {
var msg = "ZLearn"
function Bigthings() {
console.log(msg.toUpperCase())
}
function Smallthings() {
console.log(msg.toLowerCase())
}
//向外暴露对象
window.myModule = {
Bigthings: Bigthings,
Smallthings: Smallthings
}
})()
html
<script type="text/javascript" src="myModule.js"></script>
<script type="text/javascript">
var module = myModule()
module.Bigthings()
module.Smallthings()
</script>
闭包的缺点
-
函数执行完之后,函数的局部变量没有释放,占用内存的时间就变长
-
容易造成内存泄漏,泄露多了,更容易引起内存溢出
意外的全局变量
function a1() { a = 1 console.log(a); } a1() console.log(a); //a变成了全局变量,在外部可访问
没有及时清理的计时器或者回调函数
var intervalId = setInterval(function () { console.log(1); }, 1000) //clearInterval(intervalId)不加上这句就会不会清理
如何解决?
能不用闭包就不用闭包
及时释放