javascript中的this详解

从一个普通的javascript函数说开去:

其实,任何一个只要写过javascript的人都能看的懂如下代码,但是如下代码藏着的玄机,却很少有人去理解。先把这个神秘的代码贴上来吧。

function ShowName() {
alert(
"I am " + this.name + " of " + typeof (this));
this.extension = "extension";
}

这段代码和普通的javascript方法没有太大的区别,唯一的区别就是方法中有一个this。其实在javascript中,this往往是令很多人头疼的东西,甚至有些人“谈this色变”。因为,不像面向对象中的this,它指的就是这个类的实体。无论怎么new实体,总是属于这个类旗下的。但是javascript中就完全不一样了。但是,我还是用一句话来总结,javascript方法中的this是指该方法所属的对象

这么说吧,其实一个方法是不能独立存在的,它就像一个女人,总有属于自己的男人,那么这个this就是指这个女人的男人。有人就说了,我在页面直接写这样一个方法:

<script type="text/javascript">

 function ShowName() {
alert(
"I am " + this.name + " of " + typeof (this));
this.extension = "extension";
}

</script>

1、这样一个方法,他的“男人”是谁呢?其实,大家都知道,如果在浏览器下,他的男人就是window对象。ShowName()只是window的一个属性(一个方法)而已。那么,我们分析一下如下代码:

name = "window";
alert(window.extension);
window.ShowName();
alert(window.extension);

第一个alert,window没有extension属性,那么会输出undefined。

调用ShowName方法,ShowName的“男人”是window,window有name属性,值为window,而typeof(window)为object。因此会输出“I am window of object”。注意this.extension = "extension"这句,这句其实是给window对象添加了一个属性,因为这里的this就是window对象,因此以后window对象便有了extension这个属性。因此在后面的alert中,就会输出extension字符串来。

2、构造的男人

当然,这个方法可以属于某个对象。我们看看下面的代码,下面的代码中,该方法变成了一个新建对象的“妻子”,那么她的this也就变成了这个新建的对象。总的来说,这个方法本身是比较“放荡”的,他的所属对象是谁,她的this就指向谁,贱人!!!

var obj = { "name": "guanqq", "ShowName": ShowName};
alert(obj.extension);
obj.ShowName();
alert(obj.extension);

这时候,ShowName方法变成了obj对象的一个方法,当调用了它时,它会给obj这个对象增加一个extension属性,使obj.extension不再为undefined,而变成了字符串“extension”。

3、构造函数法

其实,这个方法可以作为构造函数,来构建一个对象,这时候,它又开始“作妈”了,它作妈的时候,“男人”对象正是通过它生成的新对象。这个虽然有点乱伦,但是事实却是如此,有例子为证!

var who = new ShowName();
who.name
= "who";
who.ShowName
= ShowName;
alert(who.extension);
who.ShowName();

在以上例子中,其实是调用了两次ShowName方法,第一次是作为构造函数调用的,这时候的this就是who,但是,这时候的who只是一个新生儿,什么属性都没有,在firebug下查看,发现this(who)只是一个{}。因此首先会输出"I am undefined of object"。等到构造函数执行完了,who就有了一个属性——extension。因为构造函数中的this就是who,给它加了一个extension属性。

然后我们在外边给who加了一个name属性。(who.name = "who";

然后,我们把ShowName送给了who做它的方法,这个和它作为who的构造函数已经没有任何关系了。这就好比以前ShowTime生下who后,两个人就失散了,后来苍天作孽,让他们做了夫妻,他们谁也不认识谁,悲剧啊!具体的不说了吧,反正ShowName变成了who的一个方法,当调用此方法的时候,就和2一样,ShowTime的this就是它的男人——who。

4、自己、本身

ShowName.ShowName = ShowName;
alert(ShowName.extension);
ShowName.ShowName();
alert(ShowName.ShowName.extension);
alert(ShowName.ShowName.ShowName.extension);
alert(ShowName.extension);

看了上面的代码,是不是有一种想砸人的冲动。淡定……

其实,ShowName本身就是一个对象(正如有个牛人说的,方法和对象的唯一差别就是方法多了一对括号,可以当方法用),作为一个对象,它是可以有属性和方法的。(就像一个男人就可以娶老婆一样)。但是,它本身也是一个方法,因此,它可以作为它的方法,这就是ShowName.ShowName = ShowName;的含义。

对于第一个alert而言,ShowName只是有了自己的方法ShowName,但是这个方法没有执行过,因此没有附加extension属性,因此为undefined。

第三句是给ShowName对象添加了extension属性。特别注意,ShowName的ShowName方法其实就是它本身,因此ShowName方法也可以看成一个对象,这个对象也有extension属性和ShowName方法……

通过alert(ShowName.ShowName===ShowName);返回true可以知道,ShowName的ShowName方法的确是它本身。

由以上可以看成,this并不是很难,只要记住方法中的this就是方法的依附对象,那么问题会迎刃而解的。记住,javascript世界中没有无缘无故的方法调用,总是有对象依附的。

ps:有人会说,var obj=new ShowName();的时候,调用构造函数,根本就看不出ShowName方法是依附于obj的,倒像是依附window对象的。其实不是的,上面一句的执行其实等价于下面的执行:var obj={};ShowName.call(obj);这么一看,真相就大白了!


posted @ 2011-03-30 01:58  公子姬良  阅读(243)  评论(0编辑  收藏  举报