在JavaScript面向对象编程中使用继承(2)

简介:
  昨天扔了一堆JavaScript类'继承'的代码,这些代码其实并不是所有的都能正常的执行。不是我不原意写出都能好好执行的继承类代码,而是这些方法本身就各自有自己的优缺点。下面我分别说它们的原理和使用时注意事项。

    构造继承法的原理:

    构造继承法关键代码是 function ArrayList01()中的:
None.gif  this.base = CollectionBase;
None.gif   this.base(); 

    这里的base不是C#派生类中的base那个概念,完全就是一个任意的JavaScript变量名。调用 this.base();其实就是执行的CollectionBase();,不过 不是 new CollectionBase();哦!没有 new基类那么怎么得到CollectionBase中的方法和属性呢?这里使用了 this作用域的一个hack,'欺骗'了脚本引擎。当我们从类ArrayList01的构造函数中调用 this.base();时,在基类CollectionBase中的 this就是ArrayList01的一个实例,于是执行CollectionBase的构造函数,就动态的把基类的成员和方法attach到ArrayList01实例中了。构造法的问题也就是从这里产生了,注意哦。

    构造继承法的缺陷:

    第一个问题,关键是出在上面那两段代码上,因为始终没有 new基类呀。这样带来的问题就是不能把基类CollectionBase中的原型属性和方法attach到ArrayList01的实例中,啊,这样还算是什么继承啊?! 所以在 上篇文章中我为了不改动CollectionBase类,而单独为其实现了一个Add()方法(只是为了统一示例代码而已)。解决这个缺陷的方法其实也很简单,就是要求基类不能使用prototype来导入属性和方法,而要把所有的属性和方法都写到构造函数中去,分别是: this.Attribute = ...; 和 this.Method = function() {...};这种形式。
    第二个问题,是 this.base = CollectionBase;和 this.base();必须写在派生类构造函数的最开头(不是一定要是第一行和第二行,而是它们的前面不能有 this.xxx这种定义为ArrayList01导入的任何属性或方法),因为调用 this.base();时会向 this(ArrayList01的一个实例)中注入基类的属性和方法,如果基类中有和 this中已导入的属性和方法重名的,就自动覆盖掉子类中的方法。
    第三个问题,是子类也不能使用prototype来导入属性和方法,这和问题二中的重名覆盖道理一样,由于prototype导入的属性和方法在子类一 new的时候就生成了,所以也存在和基类重名而被覆盖的潜在错误威胁。解决办法,和基类编写规则一样不要使用prototype,并且将子类的属性和方法定义代码放在导入继承的代码( this.base = CollectionBase; this.base();)之后。

    构造继承法的示例:   
ExpandedBlockStart.gif < script  language ="JavaScript" >
InBlock.gifdocument.write('构造继承法:
< br > ');
InBlock.gif
var  arrayList11  =   new  ArrayList01();
InBlock.gifarrayList11.Add('a');
InBlock.gifarrayList11.Add('b');
InBlock.gifarrayList11.foo();
InBlock.gif
var  arrayList12  =   new  ArrayList01();
InBlock.gifarrayList12.Add('a');
InBlock.gifarrayList12.Add('b');
InBlock.gifarrayList12.Add('c');
ExpandedBlockEnd.gifarrayList12.foo();
None.gif
</ script >

    示例运行结果为:
None.gif构造继承法:
None.gif[class ArrayList01]: 2: a,b
None.gif[class ArrayList01]: 3: a,b,c

    小结一下:JavaScript的构造继承法其实看起来还是比较直观的,因为子类构造函数中有对基类构造函数的调用,似乎在语法上还比较容易被接受。可是由于没有 new基类,带来了不能获得prototype导入的属性和方法的缺陷。解决这个缺陷的方法虽然不难,可是由此而给基类编写限制一个凌驾于JavaScript语法规范的规则,可操作性不是很好。子类也不能利用prototype特性来导入属性和方法,会与基类之间存在潜在的重名覆盖问题。所以对于复杂的基类,不推荐这种继承方法,因为类复杂了,使用prototype可以规范类代码,使类的定义看起来比较的舒服 emwink.gif

    应用场景:小规模类之间的继承,基类和子类的属性方法在5-8个。还有就是以构造函数中赋值方式导入类的属性和方法,而不用prototype导入的类编写习惯的时候。


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

目录
相关文章
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(一)
深入JS面向对象(原型-继承)
31 0
|
1月前
|
JavaScript 前端开发
js开发:请解释原型继承和类继承的区别。
JavaScript中的原型继承和类继承用于共享对象属性和方法。原型继承利用原型链查找属性,节省内存但不支持私有成员。类继承通过ES6的class和extends实现,支持私有成员但占用更多内存。两者各有优势,适用于不同场景。
19 0
|
3月前
|
JavaScript
|
3月前
|
存储 前端开发 JavaScript
揭秘原型链:探索 JavaScript 面向对象编程的核心(下)
揭秘原型链:探索 JavaScript 面向对象编程的核心(下)
揭秘原型链:探索 JavaScript 面向对象编程的核心(下)
|
3月前
|
前端开发 JavaScript 开发者
揭秘原型链:探索 JavaScript 面向对象编程的核心(上)
揭秘原型链:探索 JavaScript 面向对象编程的核心(上)
揭秘原型链:探索 JavaScript 面向对象编程的核心(上)
|
3月前
|
存储 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(三)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
3月前
|
设计模式 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(一)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
3月前
|
存储 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(二)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
1月前
|
设计模式 JavaScript 前端开发
JavaScript中继承的优缺点
JavaScript中继承的优缺点
13 3
|
1月前
|
JavaScript 前端开发
如何在 JavaScript 中实现继承?
如何在 JavaScript 中实现继承?
11 2