共计 3701 个字符,预计需要花费 10 分钟才能阅读完成。
上节:javascript 类学习资料(一):http://suiyidian.cn/post-61.html
构造函数
一个类在初始化的时候其实也是一个函数的执行过程,这个函数就是构造函数,我们看一下下边的代码:
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); // 泣红亭
构造函数不需要返回值,但如果你设置了返回值,可以把它当成一个函数来使用。
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,因此不打算讲,只是说说它的一点点思想以供参考。
在上边男孩的继承问题中,男孩其实不仅仅是继承自男人,还继承自孩子(有男孩子,也有女孩子)这个类,因此,它同时继承了两个类:男人与男孩,这就是所谓的多重继承。
先看第一个类的定义
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()
{
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 = “ 泣红亭 ”;
}
定义类作为一个对象时的属性:
WuYouUser.Url = “http://suiyidian.cn”; // 静态属性的定义是:WuYouUser.prototype.Url = “http://suiyidian.cn”;
var Wo = new WuYouUser();
document.write(WuYouUser.Url); //http://suiyidian.cn
document.write(Wo.Url); //undefined, 即未定义!注意这里的未定义
从这里可以看出 Url 这个属性是 WuYouUser 自个所有,改变了它与其它类以及它的子类完全无关!
引用类的属性只有一个办法,就是类名. 属性名,改变它也一样。
定义类作为一个对象时的方法:
WuYouUser.ChangeUrl = function()
{
this.Url = “http://suiyidian.cn”;
}
你或许会觉得奇怪,这里的 this 是什么?因为 ChangeUrl 这个方法是属于对象 WuYouUser 的,因此 this 指的就是 WuYouUser 本身!
可以运行下边的代码试试:
document.write(WuYouUser.Url); // http://suiyidian.cn
WuYouUser.ChangeUrl();
document.write(WuYouUser.Url); // http://suiyidian.cn
明显 ChangeUrl 直接修改了 WuYouUser.Url 的值,因此后边才能输出 http://suiyidian.cn