闭包(closure),是指有权访问另一个函数作用域的变量的函数。
闭包的简单理解就是:函数里面放一个匿名函数。
创建闭包的常见方式就是在一个函数里面创建另一个函数。
例1: 下列的f2函数实际上就是一个闭包。
function f1(){
var n = "test";
function f2(){
alert(n);
}
return f2;
}
var result = f1();
result();
//结果为:test
例2:认识闭包,首先通过下面的例子对比了解嵌套函数的词法作用域规则:
var scope = "global";
function check(){
var scope = "local";
function fn(){
return scope;
}
return fn();
}
alert(check()); //结果:local
变形之后为:
var scope = "global";
function check(){
var scope = "local";
function fn(){
return scope;
}
return fn;
}
alert(check()()); //结果:local
例子说明:由于JavaScript词法作用域的规则是:JavaScript函数执行用到了作用域链,这个作用域莲是函数定义的时候创建的。
在上述函数中,嵌套的函数fn()定义在这个作用域链中,其中的变量scope是一个局部变量,不管在何时何地执行函数fn()时,这种绑定在执行fn()时都有效,所以执行结果是“local”。
以上例子对比体现闭包可以捕获到局部变量(和参数),并一直保存先来,看起来就像这些变量绑定到了在其中定义他们的外部函数中。
闭包的本质:闭包是连接函数内部和外部的一座桥梁。
闭包的用处:(1)读取函数内部的变量。 (2)让这些变量的值始终保存在内存中,实现数据共享。
例3:使用无名函数定义闭包。
var count = (
function(){
var i = 0;
return function(){
alert(i);
++;
}
}
)();
count(); //结果:0
count(); //结果:1
count(); //结果:2
以上形式可理解为:
自我执行函数执行匿名函数: (匿名函数)(); //第一个()里面放匿名函数,第二个()执行。
例4:使用匿名函数实现局部变量驻留内存,从而实现累加。
function count(){
var age = 0;
return function(){
age++;
return age;
};
}
var b = count();
alert(b()); //结果:1
alert(b()); //结果:2
alert(b()); //结果:3
例5:向闭包内部传入参数
var count = (
function( num ){
return function(){
alert(num);
num++;
}
}
)(5);
count(); //结果:5
count(); //结果:6
count(); //结果:7
例6:调用时指定参数
var count = ( function() {
var i = 0;
return function (num) {
num += i;
alert(num);
num++;
}
}
)();
count(8); //结果:8
count(9); //结果:9
count(10); //结果:10
闭包只能取得包含函数中任何变量的最后一个值,因为闭包所保存的是整个变量对象,而不是某个特殊的变量。
特别注意:由于闭包会携带包含它的作用域,因此会比其他函数占用更多的内存。
闭包的使用:在同一个作用域链中定义两个闭包,这两个闭包共享同样的私有变量。
function count(num){
return function(){
return num;
};
}
var array = [];
for(var i=0; i<10; i++){
array[i] = count(i);
}
alert(array[5]()); //结果:5
对比
function count(){
var array = [];
for(var i=0; i<10; i++){
array[i] = function(){
return i;
}
}
return array;
}
var array = count();
alert(array[5]()); //结果:10