多数JavaScript的开发者仅仅把JavaScript作为一种Script语言使用,没有意识到JavaScirpt有着强大的基于对象的功能,实际上,
JavaScript可以支持完善的面向对象编程范典(paradigms),许多实用的JavaScript控件都是使用JavaScript的基于对象开发的。
本文将叙述在Javascipt中如何实现封装,继承,多态。
1. Object 对象
Object 对象是JavaScript的基本对象,在任何其它JScript对象中都包含有Object对象,在所有其它对象中它的方法和属性都是可用的。可以认为Object是所有JavaScript类的基类。在用户定义的对象中可以重载Object类的方法,例如 toString 方法是一个经常被重载的例子。
由于是一种基于原型的解释型语言,JavaScript允许在任意时刻给一个对象添加任意多的属性,这一点和C++不同,C++是一种强类型的编译型语言,所有对象的方法和属性都必须先定义后使用。
例一:
obj = new Object;
obj2 = new Object;
obj.x = 1; //给obj添加属性x
obj.y = 2; //给obj添加属性y
这里,obj的属性x和y是我们额外添加的两个属性,x,y依附于obj, 在obj2中则没有x,y这两个属性。
2.对象的构造
JavaScript允许自定义类型,类型的每一个实例都拥有类型内部所定义的属性。类型的实现就是通过定义函数直接实现的,每个函数可以直接看成class,生成对象时一定要使用new关键字。
例二:
function Foo()
{
this.x = 1;
this.y = 2;
}
obj1 = new Foo;
obj2 = new Foo;
在这里任何一个根据Foo所构造出的对象都含有x,y属性。
2. prototype 属性
prototype 属性返回对象类型原型的引用.所有JScript固有对象都有只读的prototype属性,
可以为一个JScript固有对象的原型添加功能,但不能赋予该对象其他的原型。
用户自定义的对象可以被赋予其他的原型。
例如,要为 Array 对象添加返回数组中最大元素值的方法。 要完成这一点,声明该函数,将它加入 Array.prototype, 并使用它。
function array_max( ){
var i, max = this[0];
for (i = 1; i < this.length; i++)
{
if (max < this[i])
max = this[i];
}
return max;
}
Array.prototype.max = array_max;
var x = new Array(1, 2, 3, 4, 5, 6);
var y = x.max( );
该代码执行后,y 保存数组 x 中的最大值,也就是6。
3.类中的方法
Javascript允许向添加属性一样的方式添加方法,这样可以将方法的实现封装起来,调用者无需关心方法的具体实现。
function Foo()
{
this.x = 1;
this.y = 2;
this.Bar = MyMethod;
}
function MyMethod(z)
{
this.x += z;
}
obj2 = new Foo;
现在我们可以这样调用函数:
obj2.Bar(3);
上面的实现并不是很方便,利用Prototype属性更简单的实现类中的方法。
function Foo()
{
this.x = 1;
}
function Foo.prototype.DoIt()
{
this.x++;
}
obj = new Foo;
obj.DoIt();
4.继承的实现
我们可以通过prototype将两个类型关连起来的方法来实现继承.这里要注意的是基类的构造函数只被调用一次,如果每一次生成对象都需要调用的话,可以使用5中的替代方法.
// 基类定义
function TextObject(st)
{
this.st = st;
this.fVisible = true;
}
// 基类的Write方法
function TextObject.prototype.Write()
{
document.write('' + this.st);
}
// 子类的定义
function ItalicTextObject(st)
{
this.st = st;
}
// 通过改写prototype将基类和子类联系起来
ItalicTextObject.prototype = new TextObject('x');
// 子类的方法定义
ItalicTextObject.prototype.Write = ITOWrite;
function ITOWrite()
{
document.write('' + this.st + '');
}
obj1 = new TextObject('Hello, mom');
obj2 = new ItalicTextObject('Hello, world');
obj1.Write();
obj2.Write();
5.另一种继承替代的实现
定义一个方法DeriveFrom,这个方法用来关连基类和子类.
function Function.prototype.DeriveFrom(fnBase)
{
var prop;
if (this == fnBase)
{
alert("Error - cannot derive from self");
return;
}
for (prop in fnBase.prototype)
{
if (typeof(fnBase.prototype[prop]) == "function" && !this.prototype[prop])
{
this.prototype[prop] = fnBase.prototype[prop];
}
}
this.prototype[fnBase.StName()] = fnBase;
}
function Function.prototype.StName()
{
var st;
st = this.toString();
st = st.substring(st.indexOf(" ")+1, st.indexOf("("))
return st;
}
// 基类定义
function TextObject(st)
{
this.st = st;
this.fVisible = true;
}
// 基类Write方法
function TextObject.prototype.Write()
{
document.write('' + this.st);
}
// 基类IsVisible方法
function TextObject.prototype.IsVisible()
{
return this.fVisible;
}
// 子类定义
function ItalicTextObject(st)
{
this.TextObject(st);
}
// 通过DeriveFrom函数调用将基类和子类联系起来
ItalicTextObject.DeriveFrom(TextObject);
//子类Write方法
function ItalicTextObject.prototype.Write()
{
document.write('' + this.st + '');
}
obj1 = new TextObject('Hello, mom');
obj2 = new ItalicTextObject('Hello, world');
obj1.Write();
obj2.Write();
6.多态的实现
Jascript不是一种强类型的语言,我们可以通过定义同名的函数实现多态:
function Foo()
{
this.x = 1;
this.DoIt = FooMethod;
}
function FooMethod()
{
this.x++;
}
function Bar()
{
this.z = 'Hello';
this.DoIt = BarMethod;
}
function BarMethod()
{
this.z += this.z;
}
obj1 = new Foo;
obj2 = new Bar;
// 多态的例子
function Poly(obj)
{
obj.DoIt();
}
Poly(obj1);
Poly(obj2);
7.constructor属性
constructor属性是所有具有 prototype 的对象的成员,保存了对构造特定对象实例的函数的引用。 可以使用对象constructor属性判断对象的类型.
例:
x = new String("Hi");
if (x.constructor == String)
// 进行处理(条件为真)。
或
function MyFunc {
// 函数体。
}
y = new MyFunc;
if (y.constructor == MyFunc)
// 进行处理(条件为真)。
(last update:2004-12-08, to be continued...)