我对闭包的理解就是:闭包就是能够读取其他函数内部变量的函数,可以把闭包简单理解为“定义在一个函数内部的函数”。
在读了阮一峰的博客里面关于闭包的讲解之后,自己对闭包也有了一定的认识,首先在理解闭包之前必须先理解JavaScript特殊的变量作用域。
变量的作用域有两种,全局变量和局部变量。
var n = 999;
function f1(){
alert(n);
}
f1();//999
从以上代码可以看出Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量,当然了,函数外部自然就无法读取函数内部的局部变量,那么如何从外部读取内部的局部变量呢?
假如我们在函数内部定义一个函数,如下:
function f1(){
var n = 999;
function f2(){
alert(n);//999
}
}
在上面的代码中,因为函数f2
包含在函数f1
中,所以函数f2
可以访问f1
中的局部变量,那么如果我们把函数f2
作为返回值,不就可以在外部读取内部的局部变量了吗,代码如下:
function f1(){
var n = 999;
function f2(){
alert(n);//999
}
return f2;
}
var result = f1();
result(); //999
其实在上面的代码中,函数f2
就是闭包了,这里面要谈到闭包的两个作用:第一个就是读取函数内部的变量,也就是上述代码的作用。第二个就是让这些变量的值始终保持在内存中,看了下面的代码就能理解第二个作用的意思了:
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
由于函数f2
赋值给一个全局变量result
,所以函数f2
保存在内存中,而函数f2
的父函数是f1
,依赖于f1
,所以f1
也会保存在内存中,导致f1
中的变量也保存在内存中,不会被回收,这就是闭包的第二个作用。
在阅读<<javascript高级程序设计>>这本书时,发现了二个与闭包相关的例子程序,第一个是:
function createFunctions(){
var result = new Array();
for(var i = 0; i < 10; i++) {
result[i] = function(){
return i;
};
}
return result;
}
正常来说返回的结果应该是,每个函数都返回自己的索引值,但是最终结果却是,每个函数返回的都是10。这是因为每一个函数的作用域链中都保存着createFunctions()
函数的活动对象,所以它们引用的都是同一个变量i,当createFunctions()
函数返回后,i的值变成10,所以每个函数都引用着保存变量i的同一个变量对象。我们可以通过创建另一个匿名函数强制让闭包的行为符合预期,如下所示:
function createFunctions(){
var result = new Array();
for(var i = 0; i < 10; i++) {
result[i] = function(num){
return function(){
return num;
}
}(i);
}
return result;
}
第二个是:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
上面代码返回的结果是 "The Window",而不是预期的 "My Object"。我们在理解这个之前,要理解方法调用和函数调用的区别。我们将最后一句话分解成一下两句话:
var first = object.getNameFunc();
var result = first();
第一句话中调用的是object对象
中的getNameFunc()
方法,所以此时this
对象是object
,但是在第二句话中,first()
是属于函数调用,是在全局环境下调用的,所以this对象
变成了window
,所以结果相当于返回了window.name。
为什么匿名函数没有取得其包含作用域(外部作用域)的this对象呢?
每个函数被调用时,其活动对象都会自动取得两个特殊的变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。——<<Javascript高级程序设计>>
再看下面的代码:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;//将getNameFunc()的this保存在that变量中
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //"My Object"
返回的结果就是预期的"My Object",因为可以把外部作用域中的this保存在闭包可以访问到的变量中。
网友评论