-
闭包
function createComparison(propertyName){
return function(object1,object2){
var value1=object1[propertyName];
var value2=object2[propertyName];
if(value1<value2){
return -1;
}else if(value1>value2){
return 1;
}else{
return 0;
}
}
}
var object1={
name:"dudu"
}
var object2={
name:"lili"
}
var compare=createComparison("name");
var result=compare(object1,object2);
alert(result);//-1
这个是书上给的例子:
特点:-
createComparison
以匿名函数做返回值。 - 匿名函数内部引用了外部函数的变量对象的形参变量
propertyName
。
-
-
闭包定义
闭包是指有权访问另一个函数作用域中变量的函数。
就像上例,返回的匿名函数访问了外部函数作用域中的变量propertyName
-
创建闭包的方式
就是在一个函数的内部创建另一个函数。 -
闭包涉及作用域链问题
一般来讲,当函数执行完毕后,其内的局部活动对象以及相应的作用域链就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
但是,闭包的情况又有所不同。
外部函数在执行完毕后(成功返回匿名函数后),其执行环境的作用域链会被销毁,但他的活动对象仍然会留在内存中,因为匿名函数的作用域链仍然在引用这个活动对象,直到匿名函数被销毁后,外部函数的活动对象,因为没有被引用所以才会被销毁。 - 销毁匿名函数
如果返回的匿名函数没有继续被引用,那么他将被垃圾回收例程清除。
所以由上文代码中这个匿名函数目前只被compare
引用,只要不让这个已用类型继续引用这个匿名函数,那么这个匿名函数就不会有其他途径被其他变量引用了。
//这时候,我们只需要
compare=null; -
闭包涉及变量值变化问题
作用域链对于闭包的这种配置机制,引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。
function createFunction(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(){
return i;
};
}
return result;
}
result=createFunction();
alert(result0);//10
闭包在哪里?
闭包在这里!
result[i]=function(){
return i;
};
为每一个数组对象定义一个匿名函数,每个匿名函数都是返回i
的值,而这个i
的值是引用自外部函数的变量i,每当执行这个函数数组内的每一个元素时,都会执行默认函数,且返回变量i的值,但是i的值依旧是10(i没有被销毁,因为js没有块级作用域)
修改方法:
result[i]=function(num){
return function(){
return num;
}
} (i);
(i)
这样的写法,是强制外部函数执行,i为传递的参数,每传递一次参数其实就是一次函数的执行,就会为该函数创建一个执行环境以及作用域链。
这样的修改方法,使得
function(){ return num;}
这个函数为闭包函数,他引用外部函数的变量num。
【缺点】这个方法虽然解决了闭包引用变量的问题,但是实在是太占用内存了,相当于一个函数内创建了10个闭包函数,那这10个闭包函数的外部函数所占用的资源(本例中的num)也不能释放。 -
闭包涉及的this对象
一般的,在全局函数中,this等于window,而当函数作为某个对象的方法时,this等于那个对象。
不过闭包的执行环境具有全局性。因为内部函数在搜索this时,只会搜索其活动对象,然而闭包没有被其他对象调用,所以其this具有全局性
var name="the window";
var obj={
name:"my window",
getName:function(){
return function(){
return this.name;
}
}
}
alert(obj.getName()())//the window
//等价于
alert(this.name)
【解决方法】
1、把外部作用域中的this对象保存在一个闭包能够访问到的变量里。就可以让闭包访问这个对象了。
var that=this;
return function(){
return that.name;
}
2、把闭包赋给这个对象。
var name="the window";
var obj={
name:"my window",
getName:function(){
return function(){
return this.name;
}
}
}
obj.getName=obj.getName();
alert(obj.getName())//my window -
闭包的优缺点
优点:
网友评论