JavaScript 面向对象编程, 第一部分: 继承

2008-02-23 07:46:55来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  我们将向你展示 JavaScript 如何实现面向对象的语言中的: 继承. 同时, 这些例子将向你展示如何实现类的封装. 在此, 我们不会讨论多态实现.

  虽然 JavaScript 是脚本语言, 但它所支持的面向对象编程也是非常强大的. 虽然它没有类和实例, 但它有对象, 原型和隐式的继承. 我们将会解释如何模拟继承及其超类与子类之间关系的形式. 原型是理解继承概念的关键, 我们将会教你如何建立原型, 如何检测一个对象是否是另外一个对象的原型, 及其 JavaScript 的模型与 Java 面向对象编程之间的区别. 我们同样会向你展示如何检测对象所包含的各种属性的方法. 在另外一篇文章里, 我还会详细地讲解有关 "原型链 (prototype chain)" 的知识.

  本文大量地参考了 Webreference.com 中 "Object-Oriented Programming with JavaScript, Part I: Inheritance" 的内容, 许多内容我进行了详细的测试和再探讨, 以保证内容不会有太大的失误.
原文地址: http://www.webreference.com/js/column79/

  面向对象语言的特点

  面向对象设计是基于以下 3 个主要原理的: 封装, 继承和多态. 说某种程序语言是支持 OO (面向对象) 设计的, 只有在它的语法中支持以上 3 个概念才可以这么说. 这种语言应该为你提供某些方法, 以使你能很轻松地定义和使用这些范例. 封装涉及到了将某个对象变成一个 "黑盒子"的概念. 当你使用某个对象时, 你不用知道它内部是如何工作的, 你也不必理解对象是如何工作的. 这个对象只需将它绝对有用的信息以接口方式提供出来. 此对象应该给你提供友好的接口, 来让你可以使用其有限的属性集和方法集. 封装还有一层意思, 那就是说某个对象包含了它需要的每一样东西, 这包括数据和对于它的操作. 封装的概念非常的强大, 因为它允许将一个大的软件项目有效地分配给每个开发人员, 对于团队中的每个人, 他们只需要关注自己所实现的对象, 而不需要太多地关注于别人的实现. 开发项目中的开销使得开发团队中成员与接口的数量按指数级别增长. 封装是自 "软件危机" 以来最受欢迎的 OO 设计理念.

  软件的复用是 OO 设计思想中另外一个重要的特点. 在软件体系中实现此思想的主要方法就是继承. 类就是定义对象的功能. 超类是某个新类, 或者说是子类被建立的来源类. 一个子类从它的超类中继承了所的方法和属性. 实际上, 所有的子类都是被自动地生成的, 因此节省了大量的工作. 你不需要一个一个地定义这些子类. 当然, 你可以重载那些继承下来的方法和属性. 事实上, 谁也没有指出哪个子类要建立得和其超类一模一样, 除非你没有重载任何的属性和方法.

  多态可能是这个 3 个概念中最复杂的一个了. 其本质上是说, 每个对象都可以处理各种不同的数据类型. 你不必为处理不同的数据类型而建立不同的类. 其典型的例子就是画图的类, 你不必为实现画圆, 画矩形, 画椭圆而编写不同的类. 你可以建立一个足够聪明的类来调用特定的方法来操作特定的形状.

  通过函数实现继承

  虽然 JavaScript 不支持显示继承操作符, 但你可以通过其实方式实现隐式继承. 对于实现类的继承, 有 2 种比较常用的方式. 第一种将某个类定义成子类的方法是, 通过在负责定义子类函数的内部调用超类的构造函数. 看下面的示例:

// 超类构造函数
function superClass() {
this.bye = superBye;
this.hello = superHello;
}

// 子类构造函数
function subClass() {
this.inheritFrom = superClass;
this.inheritFrom();
this.bye = subBye;
}

function superHello() {
return "Hello from superClass";
}

function superBye() {
return "Bye from superClass";
}

function subBye() {
return "Bye from subClass";
}

// 测试构造特性的函数
function printSub() {
var newClass = new subClass();
alert(newClass.bye());
alert(newClass.hello());
}

  当你运行上面的 printSub 函数时, 它会依次执行 subBuy 和 superHello 函数. 我们可以看到, bye 和 hello 方法最先在 superClass 中被定义了. 然而, 在 subClass 中, bye 方法又被重载了, subClass 构造函数头两行的功能只是做了一个简单的原始的继承操作, 但它是通过显示执行 inheritFrom 方法来完成的继承操作. 继承的过程先是将 superClass 的对象原型赋给 subClass 下的 inheritFrom 方法, 然后在执行完 superClass 的构造函数后, superClass 的属性就被自动地加到了 subClass 的属性列表中.这主要是由于在 subClass 中通过 this 来调用的 inheritFrom (也就是 superClass) 构造函数造成的, 通过此种方式调用 superClass 构造函数时, JavaScript 解释器会把 superClass 中的 this 与 subClass 中的 this 理解成位于同一个作用域下的 this 关键字, 所以就产生了继承的效果.

  另外, 需要说明的是, 对于任何一个实例化的对象, 你任意地为它添加属性或方法, 如下所示:

var newClass = new subClass();
newClass.addprop = "added property to instance object";

  很明显, 通过此种方式添加的属性和方法只对当前实例化对象有效, 不会影响所有的同类型对象实例. 无疑, 它是你创造的一个独一无二的对象实例.

  通过原型实现继承

  第二种, 也是更强大的方法是通过建立一个超类对象, 然后将其赋值给子类对象的 prototype 属性, 以此方式来建立子类的继承. 假设我们的超类是 superClass, 子类是 subClass. 其 prototype 的赋值格式如下:

subClass.prototype = new superClass;

对于原型继承的实现方式, 让我们刚前面的代码改写一下, 示例如下:

// 超类构造函数
function superClass() {
this.bye = superBye;
this.hello = superHello;
}

// 子类构造函数
function subClass() {
this.bye = subBye;
}
subClass.prototype = new superClass;

function superHello() {
return "Hello from superClass";

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Javascript实现上传的图片按比例缩放和原样显示

下一篇:有关清空表单的各种可能的操作