前言:
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
1. 关于全局变量 和 局部变量的 理解:
函数外面: var a = 20; 此处var声明的a是一个全局变量
函数内部:function getAll() {
//如果是 var 声明的,则是局部变量 (与函数外面声明的相反 )
var a = 20;
//如果是直接写的(省去var声明的),则是全局变量
a = 20
}
访问范围:
全局变量,在整个script中,都可以访问到;
但是局部变量只能在函数内部访问到;函数外部是不能访问到的。
有时候,想要在全局访问到函数内部的局部变量,要怎么办?
——闭包,可以实现这一点。
2. 闭包(closure):
何为闭包?
在一个函数中写入另外一个函数,并且可以访问到这个函数的局部变量的函数,这就是闭包。
在js中,只有一个函数内部的子函数才可以读取局部变量,所以,也可以把闭包理解为“定义在一个函数内部的函数”。
(本质上,闭包就是讲函数内部和函数外部链接的一座桥梁。)
function fn1(){
var a = 20;
return function fn2(){
alert(a);
}
}
fn1()();
此处的 fn2函数就是闭包函数。
3. 闭包的作用:
第一:可以读取一个函数内部的函数,
第二:避免“垃圾回收机制”回收,因为子函数会返回一个全局变量,又会调用父函数的局部变量,两个变量相互调用;
所以,两个函数都不会被清除。
4、关于闭包中this的指向问题( 进阶版)。
代码一:
var name = 'The window ';
var object = {
name: ' my object',
fn1 : function(){
alert('1' + this.name); //此处this.name为 my object (因为会继承object)
return function(){
alert('2' + this.name); //此处this.name为The window (没有执行是上下文,所以,找到了windows )
return this.name;
}
}
}
object.fn1()();
难点:红色部分打印出来的为什么是“The window” ?
解释:
我们可以换种写法:
var obj = object.fn1()();
obj();
这里的obj()是函数体 function() { return this.name };
此处的obj指向的是window,所以this.name是The.window
代码二:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
alert(that.name); //?
return function(){
alert(this.name); //?
alert(that.name); //?
return that.name;
};
}
};
object.getNameFunc()();
解释:这里只要是that.name都是指向的“My Object”;
因为,红色的那行代码,把this的指向做了保存。
但是如果用的是,this.name依然指向的是windows(可以参考代码一中的解释)。