1、定义:
当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包
function A(){
var count = 0;
function B(){
count ++;
console.log(count);
}
return B;
}
var C = A();
C();// 1
C();// 2
C();// 3
var d = A();
d();//1
d();//2
for(var i=1;i<=3;i++){
setTimeout((function(){
var j=i;
return function(){
console.log(j);
};
})(),0);
}
//1
//2
//3
2、调用方式:
function fun(n, o){
console.log(o);
return {
fun: function(m){
return fun(m, n);
}
};
}
同一个闭包,保存相同的值
var a = fun(0); // undefined 闭包a:n === 0
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
多个闭包之间,数值互不干扰
// var b = fun(0).fun(1).fun(2).fun(3);
var b0 = fun(0); // undefined 上一次的调用该结果作为下一次的参数传入
var b1 = b0.fun(1); // 0
var b2 = b1.fun(2); // 1
var b3 = b2.fun(3); // 2
3、作用:缓存数据,避免污染全局
闭包的使用,提高性能
var fib = function(){
var cache = [];
return function(n){
if(n < 1){
return undefined;
}
var val = cache[n];
if(!val){
if(n === 1 || n === 2){
val = 1;
} else{
val = arguments.callee(n - 1) + arguments.callee(n - 2);
}
cache[n] = val;
}
return val;
};
}(); //自调执行
for(var i = 0; i < 10; i++){
console.log(fib(i));
}
4、 弊端:内存泄漏
由于闭包可以缓存数据,常驻内存, 容造成造成内存泄漏。( 将闭包变量 赋值为 null)
1. 引用计数法
当定义一个变量 (此时引用计数为0)并且 赋值为指定的数据时,该变量的引用计数 + 1;
如果该数据,有其他对象或函数使用,引用计数 + 1;
如果使用该数据的对象或函数,被GC回收掉,那么引用计数 - 1;
如果该变量手动赋值为null,此时引用计数 - 1;
当GC对象寻访到该变量时,如果计数为0,GC对象就直接回收该变量所占用的内存。
如果函数正在执行或还没有执行完毕,内部定义的数据都是不可回收的,不论引用计数是否为0。
引用计数的缺陷:容易产生循环引用,导致变量无法被GC回收。
2. 标记清除法
从文档的根节点(window对象)出发,找到至少一条路径可以到达该变量,那么该变量被标记为 “不可回收”;否则,该变量标记为 “可回收”。
当GC对象寻访到该变量,如果被标记为 “可回收”,那么,就会立即回收掉其所占用的内存。
标记清除法的缺陷:性能比较低。