Javascript中的闭包是比较难的概念,本文截取部分自JavaScript面向对象编程指南的内容,对闭包的概念进行解释。
在了解闭包之前,首先要熟悉作用域链,因为闭包的出现是为了突破作用域链。
作用域链
如果我们在一个外部函数outer()中嵌套了一个内部函数inner(),那么在inner()中可以访问的变量既来自于它自身的作用域,也可以来自其父级的作用域,这样就形成了一个作用域链。
var global = 1;
function outer () {
var outer_local = 2;
function inner() {
var inner_local = 3;
ruturn inner_local + outer_local + global;
}
return inner();
}
// 执行
> outer();
> 6
闭包
var a = "global variable";
var F = function(){
var b = "local vaiable"
var N = function() {
var c = "inner local";
};
};
首先a至于全局空间中,b位于F空间中,c位于N空间中,其中,a和b是不联通的,因为b在F之外是不可见的,但是如果我们讲c和b联通起来,把N空间扩展到F以外,我们就产生了一个有趣的东西,叫做闭包。
这样以来,N和a就同处一全局空间,因为函数还记得被定义时的环境,所以N仍然可以反问F空间和b,但是a却不能访问F空间和b。这主要是通过将它们升级为全局变量/通过F传递给全局空间实现的。
例子
通过F传递的方法:
var a = "global variable";
var F = function(){
var b = "local vaiable"
var N = function() {
var c = "inner local";
return b; // b在全局空间中不可见
};
return N;
};
var inner = F();// b对N是可见的,因为F 是全局函数,所以将F的返回值赋值给另外一个全局变量,从而生成一个可以访问F()私有空间的新全局函数;
> inner();
通过升级为全局变量的方法:
var inner; //定义全局变量
var F = function(){
var b = "local vaiable"
var N = function() {
var c = "inner local";
return b; // b在全局空间中不可见
};
inner = N;
};
var inner = F();// b对N是可见的,因为F 是全局函数,所以将F的返回值赋值给另外一个全局变量,从而生成一个可以访问F()私有空间的新全局函数;
> inner();
简而言之,如果一个函数在其父函数返回之后,仍然可以留住对父级作用域的链接,相关的闭包就会创建起来。