上一篇文章讲了局部变量与全局变量,我们来回顾一下。
全局变量 vs 局部变量
全局变量:优:反复使用,且共享使用
缺:可能随时在任意位置被篡改——全局污染
建议:尽量避免使用全局变量
局部变量:不可反复使用!方法调用完自动释放
解决:闭包:反复使用一个局部变量,且不会被污染
可以看到,当我们希望即重用变量,又保护变量不被污染时,可以使用闭包,那什么是闭包?
闭包: 即重用变量,又保护变量不被污染的一种机制
如何使用闭包? 3步:
1、用外层函数包裹受保护的变量和操作变量的内层函数
2、外层函数将内层函数返回
3、使用者调用外层函数,获得内层函数的对象
缺点: 比一般函数占用更多内存
//模拟取号机
//1、定义外层函数保护局部变量,并返回内部函数
function outer(){
var i = 1;
return function(){
console.log(i++);
}
}
var getNum = outer();// 指向内部函数
getNum();//1 执行函数,调用局部变量n
getNum();//2
i = 1;
getNum();//3 不受污染
var getNum1 = outer();// 重新定义一个函数,指向内部函数
getNum1();//1 执行函数,调用局部变量n
getNum1();//2
解析思路图解:
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
第七步:
第八步:
如何判断闭包?3特点:
1、内外层函数嵌套
2、内层函数必须使用了外层函数的局部变量
3、外层函数将内层函数返回到外部,可在外部调用
判断闭包结果:2句话:
1、外层函数调用了几次,就有几个受保护的局部变量副本
2、同一次外层函数调用返回的内部函数对象,操作同一个变量
function outer(){
for(var i=0,arr=[];i<3;i++){
arr[i] = function(){return i;}
}
return arr;
}
var funs = outer();
console.log(funs[0]());//?
console.log(funs[1]());//?
console.log(funs[2]());//?
解决思路:
1、先找受保护的变量,判断外层函数执行后变量的结果
2、再找操作变量的内层函数:
1、被外层函数return到外部的
2、也可通过直接给全局变量赋值一个函数的方式
解析:
//i = 3,数组funs中的函数,全部指向i,则:
console.log(funs[0]());//3
console.log(funs[1]());//3
console.log(funs[2]());//3
如何使 funs[0]()
输出0,funs[1]()
输出1?
//将 i 的值提前传进内部函数
function outer(){
for(var i=0,arr=[];i<3;i++){
arr[i] = (function(i){
return function(){
return i;
}
}(i))
}
return arr;
}
var funs = outer();
console.log(funs[0]());//0
console.log(funs[1]());//1
console.log(funs[2]());//2