注:此文总结摘自阮一峰老师http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
一、首先了解变量的作用域有两种:局部变量和全局变量。
内部函数可以访问外部变量,但函数外部不可以访问内部变量。
怎么才能够在函数外部访问局部变量呢?当然闭包是可以做到的。
二、闭包:能够读取其他函数内部变量的函数。
如:
function f1(){
var n=1;
function f2(){
console.log(n);//1
}
}
函数f2可以读取到函数f1内部的变量n
三、闭包的用途:
1、在函数外部读取函数内部的变量;(将内部函数作为返回值)
如:
function f1(){
var n=1;
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result();//1
将内部函数f2返回,可以在函数外访问变量n;
2、可以让变量的值始终保存在内存中,不会被垃圾回收机制回收;
如:
function f1(){
var n=1;
add=function(){
n=n+1;
}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
//第一次调用
result();//1
//第二次调用
add();
result();//2
以上代码正是由于这个原因,所以第一次调用后局部变量n常驻内存,add()之后才会改变。
四、闭包的缺点:
1、网页的性能问题(IE中可能导致内存泄漏):由于闭包导致变量常驻内存,内存消耗很大
解决:在退出函数之前,将不用的变量全部删除。
2、闭包会在父函数外部改变父函数内部的变量,所以必须小心。
五、与闭包运行机制相关的思考:
1、代码:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
console.log(object.getNameFunc()());
答案:undefined
原因:由于调用object.getNameFunc()之后返回一个匿名函数,而匿名函数的this默认指向window;注意:window.name没有定义。
对象外的var name = "The Window";并没有定义在window对象上,如果去掉var,则结果为The Window;
2、代码:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that=this;
return function(){
return that.name;
};
}
};
console.log(object.getNameFunc()());
答案:My Object
原因:调用getNameFunc()的对象是object,所以this指向object;