10.6 JS 原型式继承

JS的面向对象继承机制是通过原型(prototype)对象来实现的。

这里我们只介绍继承、原型的基本概念和其常见使用方式。要完整理解继承,需要读者自行补充阅读面向对象编程的发展历史和一些核心思想。简而言之,继承是为了更好的代码或接口复用。

举个例子,如果我们要在界面上构建若干个面板组件,每个面板包含不同的内容和元素,但要求每个面板都可以被隐藏或显示、漂浮或定位,那么最原始的方法是在每个面板对象中添加show/hide/float/dock方法。

这样就存在大量的代码重复和冗余,我们要把相同的代码拷贝若干份放在不同的对象实现中。

而通过继承,我们可以实现一个包含这些公共接口的基础面板对象,其他对象从他派生而来,自然继承其所有的方法,避免了重复定义和实现。

原型对象(prototype)

我们知道C++/Java语言继承是通过类(class)机制来实现的,而JS中并没有类的概念,只有对象(Object)的概念。

一个物体的原型,我们可以把它看作是物体的毛胚,我们得先有个毛胚房,然后加上自己的额外装修,可以构建自己的精装房。其内在思想是通过对象来生成新对象,被称之为组合继承。JS的继承正是通过原型对象来实现的。

语法和代码实例

我们通过代码来实际体验原型的使用:

上述代码中,定义了一个基础对象basePanel,该对象的原型包含了两个基本方法hide和show,然后分别实现了2个派生对象,headerPanel和menuPanel。

在执行这一句:menuPanel.prototype = new basePanel('menu');之前,menuPanel的默认原型对象包含一个指向自身的构造函数,执行完这一句后,该构造函数被替换成基础对象basePanel的原型, 当派生对象没有定义某函数时,会循着原型链回溯基础对象的方法。因此这两个派生对象将继承hide和show方法,而无需重复定义。

当然,我们可以在派生对象中定义新的方法或者通过重复定义相同方法来覆盖基础对象的已有实现。

ES6引入了class关键字,对继承有了更直观的语法支持,对于本章内容了解即可。