6. this.Name = "泣红亭"; //这里默认值为我的名字
}
NewClass.prototype.ChangeName = function(NewName)
{
this.Name = NewName;
}
var Wo = new NewClass();
Wo.ChangeName("郑运涛"); //我的真名
可以看到 Wo.Name 确实已经变成了"郑运涛",这个方法似乎是可以用的,但里
边是不是内有天机呢?
再看下边的代码,类的定义以及 ChangeName 的定义我们照样,但改变一下下边的
代码:
NewClass.prototype.ChangeName("郑运涛");
document.write(NewClass.Name); //undefined,即未定义
document.write(NewClass.prototype.Name); //郑运涛
var Wo = new NewClass();
document.write(Wo.Name); //泣红亭
可以看到我们并没有定义 NewClass.prototype.Name 这个静态属性,但编译器
给我们自己加了一个。
可是再看下边输出 Wo.Name,它并不是为"郑运涛",而是原来的默认值"泣红亭",
说明了什么?
其实很简单,看一下 NewClass 的定义里已经有 Name 这个属性,因此 Wo 也有自己
的 Name 属性,它跟 NewClass.prototype.Name 并不是同一个的,因此就还是那样
子。
那为什么前一个例子运行了 Wo.ChangeName("郑运涛")却能够实现改变
Wo.Name 属性呢?其实在这里跟改变 Wo.Count 的值是同一个道理,编译器自动给
Wo 增加了一个方法 ChangeName,这个方法代码与 NewClass.prototype.ChangeName
一样,但 Wo.ChangeName 是 Wo 这个实例所特有的,而非
NewClass.prototype.ChangeName!
分析可知道在静态方法里尽量不要使用 this 这样的关键字来引用实例本身的
属性,除非你有特别的目的,而且能够清楚地明白这里边的运行机制!
如果真的需要在静态方法里使用 this,可以直接把 this 当作参数传进去:
NewClass.ChangeName = function(This,NewName) //注意这里是 This,不是
this
{
7. This.Name = NewName;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
构造函数
一个类在初始化的时候其实也是一个函数的执行过程,这个函数就是构造函数,
我们看一下下边的代码:
function WuYouUser()
{
this.Name = "泣红亭"; //默认定义为泣红亭
alert(this.Name);
}
var Wo = new WuYouUser();//可以看到出现一个窗口显示泣红亭三个字
可以看出类的定义不仅仅是定义了它的属性与方法,还同时可以加入一些代码,
而这些代码就是该类的构造函数的代码,在实例声明过程中被执行!
其实说起来,类的属性与类的方法都是在构造函数里执行定义的,看下边的代码:
function WuYouUser()
{
this.Name = "泣红亭";
return;
this.Sex = "男";
}
var Wo = new WuYouUser();
document.write(Wo.Name); //泣红亭
document.write(Wo.Sex); //undefined,即未定义
看得出什么?Sex 属性是在 return;之后的,而 WuYouUser 类的构造函数遇到
return 即停止运行,换句话说 this.Sex = "男";这一行是没有被执行,即 Sex 属
性根本没有被定义!
构造函数可以有参数,参数值在声明实例的时候被传入:
function WuYouUser(Name)
{
this.Name = Name;
}
var Wo = new WuYouUser("泣红亭");
document.write(Wo.Name); //泣红亭
构造函数不需要返回值,但如果你设置了返回值,可以把它当成一个函数来使
用。
8. function Sum(a, b)
{
this.a = a;
this.b = b;
return this.a + this.b;
}
document.write(Sum(12, 23)); //输出的是 12 与 23 的和 35
var Obj = new Sum(12,23);
document.write(Obj.a) // 12
document.write(Obj.b) // 23
感觉挺奇妙,对吧?我写这文章写着写着也觉得挺奇妙的,呵呵!
但强烈建议不要把一个类当成一个函数来使用!如果你需要的是一个函数,请
直接写成函数而不要写成类,以免搞混了。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
继承
继承这个词在面向对象的编程里是非常重要的,虽然 JavaScript 并不是真正
面向对象的语言,而是跟 VB 一样是基于对象的语言,它同样提供了继承机制。
文章开头时谈到了男人与女人,这也同样是两个不同的类,但却具有相同的一
些属性以及方法,而这些相同的特性是来自“人”这个类的,换句话说男人与女人
继承了“人”的所有特性!但是男人与女人却有其不同的地方,编程语言里的继承
也一样,一个类 A 继承了另一个类 B,那么类 B 就是类 A 的父类,类 A 就是类 B 的
派生类,也称为子类。 比如男人就是人的派生类,而人就是男人的父类。 最高一级的
类称为基类,想象一下就可以明白,男人继承自人,男孩继承自男人,人就是男孩
的基类,男人就是男孩的父类。
>>>>>>>>>>>>>>>>>>>>
题外:多重继承
这里再涉及一个多重继承的话题,但如果你仅仅是学 JavaScript 的话就没有
必要看下去,因为 JavaScript 不提供多重继承,准确一点说没有一种简单而标准
的方法来实现多重继承(其实是有办法实现的,只不过麻烦了一点,而且确实没有
必要)。
在 C++中是有多重继承的概念的,这里是讨论 JavaScript,因此不打算讲,只
是说说它的一点点思想以供参考。
9. 在上边男孩的继承问题中,男孩其实不仅仅是继承自男人,还继承自孩子(有
男孩子,也有女孩子)这个类,因此,它同时继承了两个类:男人与男孩,这就是
所谓的多重继承。
好,这个问题打住,我们还是回归主题。
>>>>>>>>>>>>>>>>>>>>
先看第一个类的定义:
function A()
{
this.Name = "泣红亭";
alert(this.Name);
}
这个类定义了一个属性 Name,默认值为"泣红亭"
现在看第二个类的定义:
function B()
{
this.Sex = "男";
alert(this.Sex);
}
定义了一个属性 Sex,默认值为"男"
继承的方式就是 子类.prototype = new 父类();
现在我们来让 B 类继承 A 类:
B.prototype = new A();
运行这一段代码:
var Obj = new B(); //首先打开警告窗口显示"泣红亭",再显示"男"
可以从上边的结果看出 B 类继承了 A 类,拥有了 A 类的属性 Name,并且执行了
A 类的构造函数,而且 A 类的构造函数在 B 类的构造函数执行之前执行。 因此我们利
用这个可以实现重写父类的方法以及重设置父类某属性的默认值:
function A()
{
10. this.Name = "泣红亭";
this.Show = function()
{
alert("这是 A 类的 Show 方法");
}
alert(this.Name);
}
function B()
{
this.Name = "郑运涛";
this.Show = function()
{
alert("这是 B 类的 Show 方法");
}
alert(this.Name);
}
var Obj = new B();
Obj.Show();
结果出现了三次警告窗口,第一个内容为泣红亭,是执行 A 类的构造函数里的
alert(this.Name),那时候 Name 属性值还为"泣红亭",因为 B 类的构造函数还没执
行,第二次内容为"郑运涛",这是 B 类里的 alert(this.Name),因为 B 类的构造函
数里给 Name 重赋值为"郑运涛"。最后是调用了 Obj.Show(),执行了不是 A 类的
Show 方法里的 Show(显示"这是 A 类的 Show 方法"),而是执行了 B 类的 Show(显
示"这是 B 类的 Show 方法"),很明显 Show 方法被重写了。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
类作为一个对象时的属性与方法(不知道如何简洁地表达,因此用了这么长的题目)
不知道在这里谈这个话题是否有点混人耳目,但又觉得不谈这篇文章就不算完
整,因为文章目的就是要让人搞清楚类的方方面面。
看了这一小节的题目,或许你会觉得奇怪,类就是类,怎么会“作为一个对象
”呢?在 JavaScript 里,一切都是对象,包括类!对象可以有属性,可以有方法,
类也同样可以有,但这个非常容易跟前边说到的静态属性与静态方法搞混了,因此
要仔细看清楚两者的分别!
定义一个类:
function WuYouUser()
{
this.Name = "泣红亭";
}