• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
新能源汽车行业用户产品设计
新能源汽车行业、面向C端用户的产品设计
博客园    首页    新随笔       管理     

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

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

 

    构造继承法的原理:

 

    构造继承法关键代码是function ArrayList01()中的:

  this.base = CollectionBase;

  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();)之后。

 

    构造继承法的示例:   

<script language="JavaScript">

document.write('构造继承法:<br>');

var arrayList11 = new ArrayList01();

arrayList11.Add('a');

arrayList11.Add('b');

arrayList11.foo();

var arrayList12 = new ArrayList01();

arrayList12.Add('a');

arrayList12.Add('b');

arrayList12.Add('c');

arrayList12.foo();

</script>

    示例运行结果为:

构造继承法:

[class ArrayList01]: 2: a,b

[class ArrayList01]: 3: a,b,c

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

 

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

 

 

声明:此文章部分或者全部内容来源于网络,如果侵犯到您的权利,请电邮我(dushizhuma(a)163.com),我将在第一时间内删除此文章并送出我的歉意!

posted @ 2007-04-12 14:58  阿一(杨正祎)  阅读(511)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3