闭包
函数的ao通过scope chain相互连接起来使得函数体内的变量都可以保存在函数的AO,这样的特性称为“闭包”。
什么时候会产生闭包?
只要你把一个函数里面的函数,作为 return 的方式返回到外边,扔给一个变量。只要做这个事刚才的调用就产生了闭包。
闭包的危险
闭包会造成原有ao不释放,产生内存泄漏,或者说是内存不合理占用。
闭包原理图解
因为outer Activation object 一直不能释放,就形成了一个闭包
闭包的应用
1,实现公有变量
//累加器
function add(){
var conut = 0;
function addAction(){
conut++;
console.log(conut);
return conut;
}
return addAction();
}
var myadd = add();
myadd();
myadd();
myadd();
myadd([1]);
myadd();
2, 缓存存储结构
function add(){
var conut = 0;
function addAction(){
conut++;
console.log(conut);
return conut;
}
function clearAction(){
conut=0;
console.log(conut);
return conut;
}
return [addAction,clearAction];
}
var myadd = add();
myadd[0]();
myadd[0]();
myadd[0]();
myadd[0]();
myadd[1]();
myadd[0]();
myadd[0]();
3, 封装,实现属性私有化
//鼓励使用方法,不鼓励直接操作变量
function counter(){
var conut = 0;
var adder= {
addAction: function () {
conut++;
console.log(conut);
return conut;
},
clearAction: function () {
conut=0;
console.log(conut);
return conut;
}
};
return adder;
}
var myCounter = counter();
myCounter.addAction();
myCounter.addAction();
myCounter.addAction();
myCounter.addAction();
myCounter.clearAction();
myCounter.addAction();
myCounter.addAction();
myCounter.addAction();
myCounter.addAction();
4,模块化开发,防止污染全局变量
如果我们从别人的地方copy过来的代码的变量和自己的变量重复,两段代码分开都运行正常,但是放到一起可能就会出错,所以用闭包的方法把他们封装在一个函数里面返回出来,就可以避免这种情况发生。
在大型公司模块化开发,全部使用闭包,不允许使用公有变量
练习1 面试题
function outer(){
var num=100;
function add(){
num++;
console.log(num);
}
return add;
}
var fn= outer();
fn();// 101
fn();//102
fn();//103
var fn2= outer();
fn2();// 104
fn2();// 105
练习2 面试题
function outer(){
var result= new Array();
for (var i = 0;i< 2;i++){
result[i] = function(){
return i;
};
}
return result
}
var fn = outer();
console.log(fn[0]()); // 2
console.log(fn[1]()); // 2
分析
解决上面这种问题的思路
- 立即执行函数
- 立即执行函数内部再声明函数
function outer(){
var result= new Array();
for (var i = 0;i< 2;i++){
result[i] = function(x){
function f2(){
return x;
}
return f2;
}(i);
}
return result
}
var fn = outer();
console.log(fn[0]()); // 0
console.log(fn[1]()); // 1