《 JavaScript高级程序设计》第四章 继承

截取自读书频道

http://book.csdn.net/bookfiles/110/index.htm


4.2.1  继承的方式

1. 对象冒充object masquerading

构造函数使用this关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使ClassA的构造函数成为ClassB的方法,然后调用它。ClassB就会收到ClassA的构造函数中定义的属性和方法。例如,用下面的方式定义ClassAClassB

  关键字 this 引用的是构造函数当前创建的对象。不过在这个方法中, this 指向的是所属的对象。这个原理是把 ClassA 作为常规函数来建立继承机制,而不是作为构造函数。如下使用构造函数 ClassB 可以实现继承机制:

这段代码中,为ClassA赋予了方法newMethod(记住,函数名只是指向它的指针)。然后调用该方法,传递给它的是ClassB构造函数的参数sColor。最后一行代码删除了对ClassA的引用,这样以后就不能再调用它。

所有的新属性和新方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法

对象冒充可以支持多重继承。如果存在两个类ClassXClassYClassZ想继承这两个类,可以使用下面的代码:

这里存在一个弊端,如果ClassXClassY具有同名的属性或方法,ClassY具有高优先级,因为继承的是最后的类。

由于这种继承方法的流行,ECMAScript的第三版为Function对象加入了两个新方法,即call()apply()

2. call()方法

call()方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作this的对象。其他参数都直接传递给函数自身。例如:

在这个例子中,函数sayColor()在对象外定义,即使它不属于任何对象,也可以引用关键字this。对象objcolor属性等于"red"。调用call()方法时,第一个参数是obj,说明应该赋予sayColor()函数中的this关键字值是obj。第二个和第三个参数是字符串。它们与sayColor()函数中的参数prefixsuffix匹配,最后生成的消息"The color is red, a very nice color indeed"将被显示出来。

要与继承机制的对象冒充方法一起使用该方法,只需将前三行的赋值、调用和删除代码替换即可:

里,想让ClassA中的关键字this等于新创建的ClassB对象,因此this是第一个参数。第二个参数sColor对两个类来说都是唯一的参数。

3. apply()方法

apply()方法有两个参数,用作this的对象和要传递给函数的参数的数组。例如:

这个例子与前面的例子相同,只是现在调用的是apply()方法。调用apply()方法时,第一个参数仍是obj,说明应该赋予sayColor()中的this关键字值是obj。第二个参数是由两个字符串构成的数组,与sayColor()的参数prefixsuffix匹配。生成的消息仍是"The color is red, a very nice color indeed",将被显示出来。

该方法也用于替换前三行的赋值、调用和删除新方法的代码:

同样的,第一个参数仍是this。第二个参数是只有一个值color的数组。可以把ClassB的整个arguments对象作为第二个参数传递给apply()方法:

当然,只有超类中的参数顺序与子类中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。此外,还可使用call()方法。

4. 原型链

在上一章中学过,prototype对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。

如果用原型方式重定义前面例子中的类,它们将变为下列形式:

原型链的神奇之处在于突出显示的代码行。这里,把ClassBprototype属性设置成ClassA的实例。

子类的所有属性和方法都必须出现在prototype属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为prototype属性被替换成了新对象,添加了新方法的原始对象将被销毁。

在原型链中,instanceof运算符的运行方式也很独特。对ClassB的所有实例,instanceofClassAClassB都返回true。例如:

ECMAScript的弱类型世界中,这是极其有用的工具,不过使用对象冒充时不能使用它。

原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的prototype属性。

5. 混合方式

创建类的最好方式是用构造函数方式定义属性,用原型方式定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。用这两种方式重写前面的例子,代码如下:

在此例子中,继承机制由两行突出显示的代码实现。在第一行突出显示的代码中,在ClassB构造函数中,用对象冒充继承ClassA类的sColor属性。在第二行突出显示的代码中,用原型链继承ClassA类的方法。由于这种混合方式使用了原型链,所以instanceof运算符仍能正确运行。

4。3其他继承方式

4.3.1  zInherit

原型链实际上是把对象的所有方法复制给类的prototype对象。还有其他方法可以实现它吗?有,利用zInherit库(可以从http://www.nczonline.net/downloads处下载),不必使用原型链,也可实现方法继承。这个小库支持所有的现代浏览器(MozillaIEOperaSafari)及一些旧的浏览器(Netscape 4.xIEMac)。

要使用zInherit库,必须用<script/>标签加入zinherit.js。第5章将详细讨论引入外部的JavaScript文件。

zInherit库给Object类添加了两个方法,inheritFrom()instanceOf()。如你所料,inheritFrom()方法负担重任,负责复制指定类的所有方法。下面一行代码用原型链使ClassB继承ClassA的方法:

可用下面代码替换上面的代码:

inheritFrom()方法接受一个参数,即要复制的方法所属的类。注意,与原型链相对的是,这种方式并未真正创建要继承的类的实例,这样更安全,开发者也无需担心构造函数的参数。

为确保正确地实现继承,必须在原型赋值之处调用inheritFrom()方法。

instanceOf()方法是instanceof运算符的替代品。因为这种方式根本不使用原型链,所以这行代码无效:

instanceOf()方法弥补了这项损失,与inheritFrom()一起使用,可以跟踪所有的超类:

4.3.2  xbObjects

NetscapeDevEdge站点(http://devedge.netscape.com)有许多对Web开发者有用的信息和脚本工具。工具之一是xbObjects可以从http://archive.bclary.com/xbProjects- docs/xbObject/处下载),Netscape公司的Bob Clary2001Netscape 6Mozilla 0.6)发布时编写而成。它支持从那时起的所有Mozilla版本及其他现代浏览器(IEOperaSafari)。

 

1. 目的

xbObjects的目的是为JavaScript提供更强的面向对象范型,不止支持继承,还支持方法的重载和调用超类方法的能力。要实现这一点,xbObjects需执行许多步。

第一步,必须注册类,此时,需定义它是由哪个类继承而来。用下面的调用可以实现这一点:

这里,子类和超类名都以字符串形式传进来,而不是指向它们的构造函数的指针。这个调用必须放在指定子类的构造函数前。

如果新的类未继承任何类,调用registerClass()时也可以只用第一个参数。

第二步,在构造函数内调用defineClass()方法,传给它类名及被Clary称为原型函数prototype function)的指针,该函数用于初始化对象的所有属性和方法(之后会介绍更多),例如:

可以看到,原型函数(prototypeFunction())位于构造函数内部。它的主要用途是在适当的时候把所有方法赋予该类(在这一点上与动态原型相似)。

下一步(迄今为止是第三步)是为该类创建init()方法。该方法负责设置该类的所有属性,它必须接受与构造函数相同的参数。作为一种规约,init()方法总是在defineClass()方法后调用。例如:

你可能已注意到init()方法中调用的parentMethod()方法。xbObjects以这种方式允许类调用它的超类的方法。parentMethod()方法接受任意多个参数,但第一个参数总是要调用的父类方法的名字(该参数必须是字符串,而不是函数指针),所有其他参数都被传给父类的方法。

在这个例子中,首先调用init()方法,这是xbObjects运行所必需的。即使ClassA未注册超类,xbObejcts都会为它创建一个所有类的默认超类,即超类方法init()所属的类。

第四步也是最后一步,在原型函数内添加其他类的方法:

然后,即可以以常规方式创建ClassA的实例:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值