您的位置:首页 > Web前端 > JavaScript

Javascript系列:实现继承

2007-11-14 09:59 597 查看


本文描述了Javascript的一种继承机制实现方案。

关于Javascript的继承实现,已经有包括著名的prototype在内的N多种方案了。虽然这些方案都粉不错,但如果不好好深入学习一番,只能用其做个玩具。但是,龙生九种,种种不同,光是风格迥异的代码就已经看得人头大了,更惶论在有限的时间内细品其味了。小生天生懒散,且生平只爱读古典作品(就是 印刷品啦),因此上,虽久闻N多大名,但无缘识荆。现仗着有些开发经验,斗胆弄斧,出来卖弄一番,让大家贝戈戈笑啦。

既然不愿使用现有的方案,就只能从头发明轮子。不过这样也好,既能打造符合自己需要的架构,又能够更深入的了解和掌握javascript的特性,二者相辅相成,岂不妙哉?!就是辛苦一些。

(唉,没有身体优势,青春饭还真难吃呀。)

作为动态语言Javascript,既不完全OO,特别是不支持继承,其与OO有关的部分又与我们所熟悉的语言有很大的不同。因此,要实现继承,必须利用其语言特性和一些技巧来辅助,以达到曲径通幽的效果。这个曲径的基础就是进行拷贝,包括对prototype域和public域(挂在this下的属性和方法都是public)的拷贝。知易行难,也唯其这样,才能够更好了解和设计JS的继承机制。

在JS中要继承(也就是拷贝)某一个类,要注意拷贝的先后次序。小心的处理拷贝次序,就能够在继承的基础上实现重载。

先来看对象的实例化次序, prototype域最先被实例化,然后,随着语句的执行,public域和私有域被填充。由于public域或私有域可能会覆盖prototype域(重载),因此,应先拷贝父类的prototype域,然后是public域。在拷贝时要注意,本体已经有的属性和方法不能被覆盖。在拷贝过程中,由于prototype域先被拷贝,而添加到prototype域后,成员(属性或方法)就会出现在this域中,这一点尤其要注意。

一个继承拷贝的参考实现如下:

// 直接修改Object的原型,使所有对象都具有继承拷贝方法
Object.prototype.derive = function(derivedClass, parentClass)
{
for ( var i in parentClass.prototype ) //先拷贝原型
{
if ( derivedClass.prototype[i] == undefined ) // 只拷贝子类没有定义的原型
{
derivedClass.prototype[i] = parentClass.prototype[i];
}
}

// 要取得对象的public域,必须先实例化
// 因此会产生闭包
var _instance = new parentClass();

for (var i in _instance) // 获取public域
{
if ( this[i] == undefined ) // 只有本地没有重载的,才会拷贝
{
this[i] = _instance[i];
}
}
} // end of method derive()

在实际应用中的例子如下:
// 基类
function TBase()
{
this.myvar = 'I/'m member variable'; // 某个公开的成员变量
}

// 不会被重载的原型
TBase.prototype.func1 = function() { alert('I/'m func1'); }
// 将要被重载的原型
TBase.prototype.shouldBeOverrided = function() { alert('I/'m in TBase'); }

// 派生类
function TMyClass1()
{
this.derive(TMyClass1, TBase); // 继承拷贝!
}

// 属于派生类的方法
TMyClass1.prototype.func2 = function() { alert('I/'m func2'); }
// 重载的方法
TMyClass1.prototype.shouldBeOverrided = function() { alert('I/'m in TMyClass1'); }


var x = new TMyClass1();

x.func1(); // 调用TBase.func1
x.func2(); // 调用TMyClass1.func2
x.shouldBeOverrided(); // 调用被重载的shouldBeOverrided

拷贝次序将如下所示:
原型拷贝:
derive方法:本身已经有了(来自Object),不被拷贝
func1方法:本身没有这个方法,拷贝之
shouldBeOverrided:被重载的方法,拷贝之
public域拷贝:
shouldBeOverrided:不会被拷贝
func1:已经在原型拷贝中处理过了,不会被拷贝
derive:不会被拷贝
myvar:被拷贝

拷贝完成后的成员列表如下:
func2
derive
shouldBeOverrided
func1
myvar

至此,一个基本的继承机制就完成了。当然,这只是个基础,还有一些重要的问题,如成员变量的深层次拷贝,留至下一篇再讨论吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: