`
happmaoo
  • 浏览: 4341328 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JavaScript类

阅读更多
1JavaScript类
2类是什么?
3许多刚接触编程的朋友都可能理解不了类,其实类是对我们这个现实世界的模拟,把它说成“类别”或者“类型”可能会更容易理解一些。比如“人”这种动物就是一个类,而具体某一个人就是“人”这个类的一个实例,“人”可以有许多实例(地球人超过六十亿了),但“人”这个类只有一个。你或许会说那男人和女人不也是人么?怎么只能有一个?其实这里要谈到一个继承的东西,后边才讲,请继续看下去。
4如何建立一个类?
5在C++中是以class来声明一个类的,JavaScript与C++不同,它使用了与函数一样的function来声明,这就让许多学Jscript的朋友把类与函数混在一起了,在Jscript中函数与类确实有些混,但使用久了自然而然会理解,这篇文章是针对想进攻面向对象编程的朋友而写,就不打算一下子讨论得太深了。
6请看下边这个类的定义:
7functionWuYouUser()
8{
9this.Name;//名字
10}
11上边的代码定义了一个WuYouUser(无忧用户)类,它有个属性:Name(名字)。Name就是WuYouUser类的一个属性。
12一个类有固定的属性,但类的实例却有不同的属性值,就像我是属于“人”这个类的,性别是男,而我有一个女同学,她也属于“人”类,但她的性别属性值却为女。
13那么如何声明某个类的一个实例呢?非常简单:
14varWo=newWuYouUser();//实例一:“我”
15varBiyuan=newWuYouUser();//实例二:“碧原”(Biyuan哥,不好意思。。。嘿嘿)
16类的属性
17这个Wo(我)就是WuYouUser类的一个实例,它拥有WuYouUser给它的一切:Name属性、Sex属性以及Age属性,我们可以这样子来设置它的属性:
18Wo.Name="泣红亭";
19很简单是不是?试着运行
20window.document.write(Wo.Name);
21看看,是不是输出了我的名字:泣红亭?
22同样设置一下碧原兄的属性
23Biyuan.Name="碧原";
24运行
25window.document.write(Biyuan.Name);
26可以看到输出了"碧原",也就说明了Biyuan与Wo同样是WuYouUser类的实例,但却是不同的实体,具有不同的属性值。
27属性是可以设置默认值的,无忧里都有记录大家各自发了多少贴子,我们也同样给WuYouUser类添加一个发贴数量的属性ArticleCount
28functionWuYouUser()
29{
30this.Name;//名字
31this.ArticleCount=0;
32}
33一个无忧新用户刚注册完之后他的发贴数量为0,在上边的代码中可以看到直接给属性ArticleCount设置值为0。
34可以运行一下这样的代码:
35varWo=newWuYouUser();
36window.document.write(Wo.ArticleCount);
37可以看到输出了0,说明ArticleCount属性被我们成功设置默认值为0
38类的方法
39方法这个词不大好理解,我觉得说成行为会更容易理解。一个人具有许多共同的行为,比如睡觉、吃饭、走路等等,现在我们给WuYouUser类添加一个发贴的方法。
40functionWuYouUser()
41{
42this.Name;
43this.ArticleCount=0;
44this.NewArticle=function()
45{
46/*
47*
48*具体如何发贴我们大家都知道,不就是打打字,加加图片再按一下保存之类的按钮么?
49*关于具体如何发贴的代码没有必要在这里写出来,我们要了解的仅仅是方法的定义与使用
50*我们在这里实现一个最简单的功能,也是很重要的功能:给我们的发贴数量加上1!
51*注意:恐龙等级就是这样加出来的,因此呀……大家狂发贴吧。。。
52*/
53this.ArticleCount++;
54}
55}
56既然定义好了这个方法,我们来试试效果如何:
57varWo=newWuYouUser();
58Wo.NewArticle();
59document.write(Wo.ArticleCount);
60可以看到输出了1,说明我们发贴成功了!真是有历史纪念意义的一刻,离恐龙等级又近一步了。
61静态属性
62静态属性又称公共属性,它不属于某个类的实例,而是直接属于某个类。
63比如说无忧用户有一个属性:注册用户的数量,它是属于整个无忧用户的,而不是属于泣红亭或者谁的
64静态属性的声明方法是:
65类名.prototype.属性名=属性值;
66比如给WuYouUser类定义一个注册用户的数量Count:
67WuYouUser.prototype.Count=0;
68那么如何读取它呢?有两种方法:
691.直接用WuYouUser.prototype.Count
702.使用Wo.Count
71这两者没有区别,都是得到0
72虽然读取方法可以有两种,但在改变它的时候却得特别小心了,请看下边代码
73varBiyuan=newWuYouUser();
74WuYouUser.prototype.Count++;
75document.write(Wo.Count);
76document.write(Biyuan.Count);
77你会发现两者的Count属性都是1,也就是说WuYouUser.prototype.Count改变了会影响到各个实例的相应属性,其实原理就是Wo、Biyuan的Count属性与WuYouUser.prototype.Count根本就是同一个!
78现在来看另外一段代码:
79varBiyuan=newWuYouUser();
80Biyuan.Count++;//特别注意一下这里,这是直接改变Biyuan的Count属性
81document.write(Biyuan.Count);//输出1
82document.write(WuYouUser.prototype.Count);//输出0
83document.write(Wo.Count);//同样输出0,为什么?
84可以看到如果直接修改实例的静态属性值,那么会出现其它实例甚至类的静态属性与它不同步了?这是因为直接修改的时候,该实例会生成一个属于该实例的属性Count,这个时候Biyuan.Count不再与WuYouUser.prototype.Count是同一个了,也不与Wo.Count是同一个,这个Count属性是属于Biyuan自己所有的,以后改变了它也只是影响它自己而已。
85因此如果不是特别的需要,建议不管在读取还是赋值的时候,都统一使用WuYouUser.prototype.Count这样的方式,以做到万无一失!
86静态方法
87与静态属性相似,它也有个另称:公共方法,同样属于类本身的。
88静态方法的定义方式是:
89类名.方法名=function(参数1,参数2参数n)
90{
91//方法代码
92}
93我们现在就来定义一个无忧用户类的注册新用户静态方法:
94WuYouUser.prototype.AddOne=function()
95{
96//***同样具体代码不写出来,给静态属性Count增加1,表示注册用户数量又多一个
97WuYouUser.prototype.Count++;
98}
99现在我们来看看如何用它,同样有两种方法:
1001.直接使用WuYouUser.prototype.AddOne()
1012.使用某实例的AddOne()
102
103这两种方法没有什么不同:
104
105varWo=newWuYouUser();
106varBiyuan=newWuYouUser();
107document.write(WuYouUser.prototype.Count);//0
108
109Wo.AddOne();
110document.write(WuYouUser.prototype.Count);//1
111document.write(Wo.Count);//1
112document.write(Biyuan.Count);//1
113
114WuYouUser.prototype.AddOne();
115document.write(WuYouUser.prototype.Count);//2
116document.write(Wo.Count);//2
117document.write(Biyuan.Count);//2
118
119可以看出不管是使用Wo.AddOne()还是WuYouUser.prototype.AddOne()效果都是一样的,都是给WuYouUser.prototype.Count加上1
120
121现在再看一段代码:
122functionNewClass()//由于上边的WuYouUser类不合适当这个例子的代码,我声明了一个新类NewClass
123{
124this.Name="泣红亭";//这里默认值为我的名字
125}
126
127NewClass.prototype.ChangeName=function(NewName)
128{
129this.Name=NewName;
130}
131
132varWo=newNewClass();
133Wo.ChangeName("郑运涛");//我的真名
134
135可以看到Wo.Name确实已经变成了"郑运涛",这个方法似乎是可以用的,但里边是不是内有天机呢?
136再看下边的代码,类的定义以及ChangeName的定义我们照样,但改变一下下边的代码:
137
138NewClass.prototype.ChangeName("郑运涛");
139document.write(NewClass.Name);//undefined,即未定义
140document.write(NewClass.prototype.Name);//郑运涛
141varWo=newNewClass();
142document.write(Wo.Name);//泣红亭
143
144可以看到我们并没有定义NewClass.prototype.Name这个静态属性,但编译器给我们自己加了一个。
145可是再看下边输出Wo.Name,它并不是为"郑运涛",而是原来的默认值"泣红亭",说明了什么?
146其实很简单,看一下NewClass的定义里已经有Name这个属性,因此Wo也有自己的Name属性,它跟NewClass.prototype.Name并不是同一个的,因此就还是那样子。
147
148那为什么前一个例子运行了Wo.ChangeName("郑运涛")却能够实现改变Wo.Name属性呢?其实在这里跟改变Wo.Count的值是同一个道理,编译器自动给Wo增加了一个方法ChangeName,这个方法代码与NewClass.prototype.ChangeName一样,但Wo.ChangeName是Wo这个实例所特有的,而非NewClass.prototype.ChangeName!
149
150分析可知道在静态方法里尽量不要使用this这样的关键字来引用实例本身的属性,除非你有特别的目的,而且能够清楚地明白这里边的运行机制!
151
152如果真的需要在静态方法里使用this,可以直接把this当作参数传进去:
153
154NewClass.ChangeName=function(This,NewName)//注意这里是This,不是this
155{
156This.Name=NewName;
157}
158构造函数
159一个类在初始化的时候其实也是一个函数的执行过程,这个函数就是构造函数,我们看一下下边的代码:
160
161functionWuYouUser()
162{
163this.Name="泣红亭";//默认定义为泣红亭
164alert(this.Name);
165}
166varWo=newWuYouUser();//可以看到出现一个窗口显示泣红亭三个字
167
168可以看出类的定义不仅仅是定义了它的属性与方法,还同时可以加入一些代码,而这些代码就是该类的构造函数的代码,在实例声明过程中被执行!
169其实说起来,类的属性与类的方法都是在构造函数里执行定义的,看下边的代码:
170
171functionWuYouUser()
172{
173this.Name="泣红亭";
174return;
175this.Sex="";
176}
177varWo=newWuYouUser();
178document.write(Wo.Name);//泣红亭
179document.write(Wo.Sex);//undefined,即未定义
180
181看得出什么?Sex属性是在return;之后的,而WuYouUser类的构造函数遇到return即停止运行,换句话说this.Sex="";这一行是没有被执行,即Sex属性根本没有被定义!
182
183构造函数可以有参数,参数值在声明实例的时候被传入:
184functionWuYouUser(Name)
185{
186this.Name=Name;
187}
188varWo=newWuYouUser("泣红亭");
189document.write(Wo.Name);//泣红亭
190
191构造函数不需要返回值,但如果你设置了返回值,可以把它当成一个函数来使用。
192functionSum(a,b)
193{
194this.a=a;
195this.b=b;
196returnthis.a+this.b;
197}
198document.write(Sum(12,23));//输出的是12与23的和35
199varObj=newSum(12,23);
200document.write(Obj.a)//12
201document.write(Obj.b)//23
202
203感觉挺奇妙,对吧?我写这文章写着写着也觉得挺奇妙的,呵呵!
204
205但强烈建议不要把一个类当成一个函数来使用!如果你需要的是一个函数,请直接写成函数而不要写成类,以免搞混了。
206:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::继承:::::::::::::::::::::::::::::::::::::::::::::::::::
207继承这个词在面向对象的编程里是非常重要的,虽然JavaScript并不是真正面向对象的语言,而是跟VB一样是基于对象的语言,它同样提供了继承机制。
208文章开头时谈到了男人与女人,这也同样是两个不同的类,但却具有相同的一些属性以及方法,而这些相同的特性是来自“人”这个类的,换句话说男人与女人继承了“人”的所有特性!但是男人与女人却有其不同的地方,编程语言里的继承也一样,一个类A继承了另一个类B,那么类B就是类A的父类,类A就是类B的派生类,也称为子类。比如男人就是人的派生类,而人就是男人的父类。最高一级的类称为基类,想象一下就可以明白,男人继承自人,男孩继承自男人,人就是男孩的基类,男人就是男孩的父类。
209>>>>>>>>>>>>>>>>>>>>
210题外:多重继承
211
212这里再涉及一个多重继承的话题,但如果你仅仅是学JavaScript的话就没有必要看下去,因为JavaScript不提供多重继承,准确一点说没有一种简单而标准的方法来实现多重继承(其实是有办法实现的,只不过麻烦了一点,而且确实没有必要)。
213
214在C++中是有多重继承的概念的,这里是讨论JavaScript,因此不打算讲,只是说说它的一点点思想以供参考。
215
216在上边男孩的继承问题中,男孩其实不仅仅是继承自男人,还继承自孩子(有男孩子,也有女孩子)这个类,因此,它同时继承了两个类:男人与男孩,这就是所谓的多重继承。
217
218好,这个问题打住,我们还是回归主题。
219>>>>>>>>>>>>>>>>>>>>
220
221color: #
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics