定义
闭包是指有权访问另一个函数作用域中变量的函数。
A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.
讲闭包之前,我们得先讲一下变量的作用域。如下:
var foo = "global foo";
function init(){
var foo = "local foo";
function sayFoo(){
return foo;
}
return sayFoo();
}
console.log(init());
我们首先在全局声明了一个变量foo。在函数init内部,我们又声明了一个私有变量foo,接着创建了一个函数sayFoo。函数sayFoo是一个内部函数,它仅在函数init内部可用,sayFoo函数没有自己的局部变量,然而它可以访问到外部函数的变量,即在init里面声明的变量foo。
我们执行init( ),私有变量foo被声明赋值,返回函数sayFoo并执行,函数sayFoo返回私有变量foo,即“local foo”,因此结果打印“local foo”。
接下来我们看下面一个例子。
var foo = "global foo";
function init(){
var foo = "local foo";
function sayFoo(){
return foo;
}
return sayFoo;
}
console.log(init()());
执行结果和上一个例子一样,打印“local foo”,但不同的 —— 也是有意思的地方,内部函数sayFoo在执行前被其外围函数init返回了。
为了便于理解,我们将上列代码修改如下:
var foo = "global foo";
function init(){
var foo = "local foo";
function sayFoo(){
return foo;
}
return sayFoo;
}
var showFoo = init();
console.log(showFoo());
我们只是把函数init()执行后的返回值赋值给了变量showFoo,但其实showFoo就是一个闭包了。它保存了sayFoo函数被创建时的作用域和sayFoo内部存储的变量(即函数init的私有变量foo),使得私有变量foo在init函数执行后并没有被垃圾回收机制回收,而是随着showFoo的赋值和sayFoo一同被保存在了内存中。只要showFoo存在,私有变量foo一直就存在。
理解这个之后,对闭包就有一个基本的认识了。趁热打铁,可以通过一下两个例子加深理解。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
理解闭包(二)讲了一个使用闭包的常见错误。