闭包
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。
我们可以用浏览器的开发者工具来调试查看。
闭包可以有两种理解,闭包是嵌套的内部函数,另一种是包含被引用变量(函数)的对象
产生闭包的条件
函数嵌套,内部函数引用了外部函数的数据(变量/函数),执行函数定义(调用外部函数,不用调用内部函数)
闭包的作用
使函数内部的变量在函数执行完后,仍然存活在内存中(延长局部变量的生命周期)
让函数外部能直接访问函数内部的局部变量
函数执行完后,函数内部声明的局部变量一般不存在,存在于闭包中的变量才可能存在
产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f()//3
f()//4
f = null//闭包死亡(包含必报的函数对象成为垃圾对象)
闭包的应用
定义js模块
具有特定功能的js文件,将所有的数据和功能都封装在一个函数内部(私有的)。
只向外暴露一个包含n个方法的对象或函数.模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
以下是两种使用方法
//1.js
function myModule(){
//私有数据
var msg='I am Xmy'
//操作数据的函数
function dosomething(){
console.log('dosomething()'+msg.toUpperCase())
}
function dootherthing(){
console.log('dootherthing()'+msg.toLowerCase())
}
//向外暴露对象
return {
dosomething:dosomething,
dootherthing:dootherthing
}
// 返回了一个对象,这个对象有两个方法,方法名可以改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="./1.js"></script>
<script type="text/javascript">
var module=myModule()
module.dosomething()
module.dootherthing()
</script>
</body>
</html>
}
//2.js
function myModule(){
//私有数据
var msg='I am Xmy'
//操作数据的函数
function dosomething(){
console.log('dosomething()'+msg.toUpperCase())
}
function dootherthing(){
console.log('dootherthing()'+msg.toLowerCase())
}
//向外暴露对象
return {
dosomething:dosomething,
dootherthing:dootherthing
}
// 返回了一个对象,这个对象有两个方法,方法名可以改
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="./2.js"></script>
<script type="text/javascript">
myModule2.dosomething()
myModule2.dootherthing()
</script>
</body>
</html>
闭包的缺点和解决
函数执行完后,函数内的局部变量没有释放,占用内存时间会变长。容易造成内存泄漏
解决:让内部函数成为垃圾对象-->回收闭包
内存溢出
一种程序运行出现的错误
内存泄漏
占用的内存没有及时释放,内存泄漏积累多了就容易导致内存溢出。
内存中容易出现的内存溢出:
1.意外的全局变量
2.没有及时清理的计时器或回调函数
3.闭包
function fn(){
a=new Array(10000000)
console.log(a)
}
fn()
//这里没有使用var,默认在window中定义。
var interid =setInterval(function(){
console.log('---')
}, 1000);
//启动循环定时器后不清理
clearInterval(interid)
//清理定时器
Q.E.D.