1>概念:闭包是有权读取另一个函数作用域中的变量的函数。我们创建闭包常见的方式就是在一个函数内部创建另一个函数。本质上,闭包是将函数内部和外部连接起来的桥梁。
其实每一个函数都是闭包,我们可以认为每个函数都是全局作用域的子作用域。
2>作用:闭包可以读取函数内部的变量,可以让变量的值始终保持在内存中。
3>副作用:因为闭包所保存的是整个变量对象,而不是某个特殊变量,所以只能取得包含函数中任何变量的最后一个值
this的问题(arguments同样有):this对象是在运行时基于函数的执行环境绑定的,匿名函数的执行环境具有全局性,因此其this对象通常指向window。但是我们通常使用的使用需要将其的this保存在一个变量中在匿名函数中使用。
4>好处:
1》可以读取函数内部的变量
2》在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)
原因:f1是f2的父级,f2被赋给一个全局变量,这导致f2始终在内存中,而f2依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回收
function f1(){
var x=1;
var result=function f2(){
x++;
return x;
}
return result;
}
var A=f1();
console.log(A());;//2
console.log(A());//3
3》避免全局污染
var abc=(function(){
var a=1;
return function(){
a++;
return a;
}
})();
4》创建用于访问私有变量的公有方法(特权方法)。
私有变量:任何在函数中定义的变量,都可以认为是私有变量,包括函数的参数,局部变量和函数内部定义的函数。
function MyObject(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//特权方法
this.publicMethod=function(){
privateVariable++;
return privateFunction();
}
}
var public=new MyObject();
console.log(public.publicMethod());//false
5>坏处:常驻内存,增大内存使用量,使用不当容易造成内存泄漏
解释闭包的例子:
function createComparisonFunction(propertyName){
return function(obj1,obj2){
var value1=obj1[propertyName];
var value2=obj2[propertyName];
//访问了外部函数中的变量propertyName,即使这个内部函数被返回了,而且在其他地方被调用,但他仍然可以访问变量,是因为内部函数的作用域链中包含了createComparisonFunction()的作用域
if(value1<value2){
return -1;
}else if(value1>value2){
return 1;
}else{
return 0;
}
}
}
副作用:
function createFunction(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(){
return i;//它保存的是 createFunction()的活动对象,所以他们引用的都是同一个变量i,可以通过创建另一个匿名函数强制让闭包的行为符合预期。
};
}
return result;
}
符合预期:
function createFunction(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(num){
return function(){
return num;
};
}(i);
}
return result;
}