-
概念:有权访问另一个函数作用域中的变量的函数
-
特征:
(1)函数嵌套函数;
(2)在函数内部可以引用外部的变量和参数;
(3)变量和参数不会以垃圾回收机制回收。 -
产生背景:
(1)js中函数内部可以读取函数外部的全局变量,但是函数外部不可以读取函数内部的局部变量;
(2)js中,如果一个对象不在被引用,那么这个对象会被垃圾回收机制回收,否则一直长居内存中;
(3)可以解决函数外部无法读取函数内局部变量的问题; -
缺点:内存泄漏;解决办法:将不使用的局部变量指向null
-
创建方式:3步
1.外层函数包裹内层函数和要保护的变量;
2.用return将内层函数对象返回到外部;
3.调用外层函数,获得内层函数对象,并保存在外部变量中反复使用
立即执行官方的两种写法:
(function (){}());//w3c建议第一种
(function (){})();
//1. 用外层函数包裹:要保护的变量和内层函数
var cai=(function(){
var n=0;
//2. 外层函数返回内层函数
return function(){
n++
document.write(`踩+1,共${n}个踩<br>`)
}
})()
//3. 调用外层函数获得内层函数对象和闭包作用域对象
cai();
<button>Button0</button>
<button>Button1</button>
<button>Button2</button>
<button>Button3</button>
<button>Button4</button>
<script>
var btns = document.getElementsByTagName('button');
for(var i = 0; i < btns.length; i++) {
(function(i) {
btns[i].onclick = function() {
alert(i);
}
}(i))
//或则
btns[i].onclick=(function(i){
return function(){
alert(i);
}
}(i))
}
</script>
function fun(){
var res=new Array();
for(var i=0;i<10;i++){
res[i]=function(num){//定义一个匿名函数,并将立即执行的结果赋给数组,匿名函数中有一个参数num,即最终返回的值
return function(){
return num;//在匿名函数内部,又创建并返回了一个访问num的闭包使res数组中的每个函数都有自己num变量的一个副本,因此可以返回各自不同的数值了
};
}(i);//在调用每个匿名函数时,传入变量i,i将当前值复制给参数num
}
resturn res;
}
function fn(){
var num=3;
return function(){
var n=0;
console.log(++n);
console.log(++num);
}
}
var fn1=fn();
fn1();// 1 4
fn1();// 1 5
匿名函数fn的返回值被赋给了fn1,这时候相当于fn1=function(){var n=0...},并且匿名函数内部引用着fn的变量num,所以变量num无法被销毁,而变量n是每次调用时新创建的,所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁,最后就剩下孤零零的num,于是这里就产生了内存消耗的问题
定时器与闭包
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i+'');//5 5 5 5 5
},100);
}
由于js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值是5,所以此时打印出来的结果是5个5
for(var i=0;i<5;i++){
(function(i){
setTimeout(function(){
console.log(i+''); // 0 1 2 3 4
},100);
}(i)
);
}
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i+'');// 0 1 2 3 4
},100);
}