JavaScript 闭包 this

为了深入了解JavaScript的闭包百度了很多博客,其中讲的很好的文章有这么两篇:

1.http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html#comment-text

2.http://www.jb51.net/article/24101.htm

第一篇主要讲了闭包和this的理解,通俗易懂,很棒,这篇博客流传很广,其评论也很精彩,但是里面经常会出现一些“奇怪”的问题,楼主自己把几个主要的问题测试了一下,有了自己的一些结论,等会为大家一一讲述。

第二篇前半部分闭包主要copy了第一篇的相关内容,但是他这里加入了作用域链的内容,例子也举的很有针对性。

总结一下:当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们。

闭包的两个作用:一个是让外部函数可以访问函数的内部变量;另一个就是闭包使得函数内部变量的生命周期变长。

作用一好理解,作用二则是闭包是将函数内部和外部连接起来的桥梁,将内部函数的引用作为返回值赋给外部全局变量时,这个内部函数就要跟随外部变量一直存在,而内部函数的存在又依赖其父函数,所以父函数也会一直存在,内部变量也就不会在销毁,而是保存在内存里。

拜读完这两篇,楼主把其中一些比较经典+“奇怪”的例子和问题在这里给大家解释一下(本人亲测,如有疑问,可以自己按照例子再测试一下)大笑

例子1:

var name = "the window";
var object = {
name:"the object",
getName: function() {
	//var that = this;
	return function() {
		return this.name;	
	};
}
};
var result = object.getName();
alert(result());//弹出“the window”
alert(object.getName()());//弹出“the window”
这个例子是第一篇文章中的第一道题,有很多人反映自己测试的结果是啥都没有,楼主开始也遇到这样的问题,但是呢自己又把这个函数写了一遍,而不是copy人家的代码,结果就正确了。

object对象内部方法getName返回一个内部匿名函数,并把这个内部匿名函数赋给外部变量使用,当这个方法执行时存在闭包。当把返回结果赋值给一个公共变量result以后,执行result()函数,相当于执行:function(){return this.name;}(); 。这时候,this指向的是window对象。因为this的指向是由他所在函数调用的上下文决定的,而不是由他所在函数定义的上下文决定的。此时result()函数的作用域是全局作用域,对象是window,所以this.name指向window.name也就是“the window” 。


例子2:

var name = "The Window";
var object1 = {
	name:"My Object1",
	getName:function(){
		var that = this;
		return function(){
			return that.name+ "  and  " +this.name;
		};
	}
};
alert(object1.getName()());//弹出“My Object1 and The Window”
这个仍然是第一篇文章中的练习题。当执行函数object1.getName()()时,相当于执行 function(){return that.name+" and "+ this.name;}(); 。执行过程中,遇到变量that.name,函数搜索自己的变量没有这个变量,便会沿着作用域链向上查找,查找到方法getName中: var that = this; ,这里this在调用函数getName()的过程中复制给that,此时调用函数getName()的对象是object1,this指向的也是object1,并将这个对象保留下来,存在that变量中,所以that.name会显示为“My Object1”,也就是object1.name。而this.name,函数在自己的属性中找到this,他指向window,所以this.name会显示为“The Window”。

引用一句经典来总结上面的话就是:

《Javascript权威指南》:如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下); 如果嵌套函数作为方法调用,其this值指向调用它的对象。


例子3:

var name = "Window";
function Fun() {
this.name = "Fun";
this.fun = function() {
	return function() {
			document.write(this.name);
		};	
}
}
var r = new Fun().fun();
r();//屏幕上显示字符串“Window”。
这个例子其实跟上两个例子相同,前两个使用对象字面量定义的对象,这个例子使用fuction函数定义的对象。主要是为了和下一个例子作对比。 偷笑


例子4:

<span style="font-size:18px;">var w=100;
function f1(){
this.w=102;
alert(this);
function f2(){
document.write(this.w);
}
return f2;
}

var f11 = new f1();//弹出[object Object]
new f1()();//弹出[object Object],并写下100

f1();//弹出[object Window]
f1()();//弹出[object Window],并写下102</span>
第一个语句和第二个语句,均是把函数作为对象使用的,将嵌套函数f2()的引用返回,使其作用域变为全局作用域,调用时this指向window对象。

第三个语句和第四个语句则是将函数作为函数使用,所以在调用函数f1()时,this指向window对象,this.w则是window.w,是全局变量,修改了例子开头的全局变量w的值。所以此时写下102。

所以,一定要注意:你是把函数当做对象使用,还是普通函数使用。

例子5:

function outerFun()
{
 var a=0;
 function innerFun()
 {
  a++;
  alert(a);
 }
 return innerFun;  
}
var obj=outerFun();
obj();  //结果为1
obj();  //结果为2
var obj2=outerFun();
obj2();  //结果为1
obj2();  //结果为2
这个例子很棒,是第二篇博文的例子。两次运行outerFun()函数,在内存区开辟了两个区域保存内部变量和内部函数。由于闭包的作用,这两次产生的变量和函数都不会被垃圾回收机制GC马上销毁。两次执行函数obj()时,都对其保存的变量a进行操作,由于a没有被销毁,所以第一次显示1,第二次显示2;同理obj2()也是如此。由于obj1和obj2访问的a是各自维护的变量,所以他们的结果不会互相产生影响。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值