闭包 —— 有权访问另一个函数作用域中的变量的函数, 即要满足以下四个条件:
- 函数A套函数B
- 函数A中有一个变量a
- 函数B引用变量a
- 当函数B在定义它的作用域A以外的地方被调用时,它访问的依然是定义它时的作用域A。这种现象称之为闭包。
function A(){
var a = 1;
function B(){
return a;
}
return B;
}
var C=A();
C();
函数B嵌套在函数A内部;函数A返回函数B。这样在执行完var C=A( )后,变量C实际上是指向了函数B,再执行C( )后就会返回值a。这段代码其实就创建了一个闭包,因为函数A外的变量C引用了函数A内的函数B,也就是说:当函数A的内部函数B被函数A外的一个变量引用的时候,就创建了一个闭包。
闭包的注意事项 通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
// 释放对闭包的引用
add5 = null;
add10 = null;
add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的环境。在 add5 的环境中,x 为 5。而在 add10 中,x 则为 10。最后通过 null 释放了 add5 和 add10 对闭包的引用。
闭包closure()只能取得包含函数func()中任何变量的最后一个值,这是因为闭包所保存的是整个变量对象,而不是某个特殊的变量。
function f(){
var arr=[],i;
for(i=0;i<3;i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var func = f();
> func
结果:[function, function, function]
> func[0]
结果: function (){
return i;
}
为什么是 i 而不是具体某个值?
主要是因为闭包中局部变量是【引用】而不是拷贝,也就是说,这个时候的i仅仅只是i的引用而不是i的值。而因为是i的引用,所以到了外部函数执行完毕后(i已经加到10了),这个时候,i才被赋值给result数组,而此时,i的值为10
再举个例子
function say888() {
var num = 887;
var sayAlert = function() { alert(num); }
num++;
return sayAlert;
}
say888() => 888
如果要改变上面的那种情况,可以利用匿名函数的自我执行
function createFunction (){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = function(num){
return function(){
return num;
}
}(i)
}
return result;
}
这个时候的匿名函数相当于fn(0),fn(1),fn(2), 此时,数组result中保存的是函数
result[0]() = 0;
result[1]() = 1;
result[9]() = 9;
因为这个时候的 i 只是函数参数,而函数参数是按值传递的(不是按引用传递),所以这个时候匿名函数被强制执行。