原型继承是一种简化的继承机制,也是JavaScript主要支持的一种继承方式。在原型继承当中,类和实例概念被淡化了,一切从对象的角度来考虑。原型继承不再需要使用类来定义对象的结构,直接定义对象,并被其他的对象引用,这样就形成了一种继承关系,其中引用对象被称为原型对象。JavaScript能够根据原型链来查找对象之间的这种继承关系。
下面通过一个例子来实现一下类型继承:
function A(x) { //A类 this.x1 = x; //A的本地属性x1 this. get1 = function() { //A的本地方法get1() return this.x1; } } function B(x) { //B类 this.x2 = x; //B的本地属性x1 this.get2 = function() { //B的本地方法get2() return this.x2 + this.x2; }; } B.prototype = new A(1); //原型对象继承A的实例 function C(x) { //C类 this.x3 = x; //C的本地属性x3 this.get3 = function() { //C的本地方法get3 return this.x2 * this.x2; } } C.prototype = new B(2); //原型对象继承B的实例
在上面的例子中,分别定义了三个函数,然后通过原型继承方法把它们串连在一起,这样C能够继承B和A函数的成员,而B能够继承A的成员。prototype的最大特点就是能够允许对象实例共享原型对象的成员。
此时,我们可以在C的实例中调用B和A的成员。
var b = new B(2); //实例化B var c = new C(3); //实例化C alert(b.x1); //在实例对象b中调用A的属性x1,返回1 alert(c.x1); //在实例对象c中调用A的属性x1,返回1 alert(c.get3()); //返回9 alert(c.get2()); //返回4
原型继承显得非常简单,其优点也是结构简练,不需要每次构造都调用父类的构造函数,且不需要通过复制属性的方式就能快速实现继承。但是它也存在缺点:
- 每个类型只有一个原型,所以它不能支持多重继承;
- 不能很好地支持多参数或者动态参数的父类。也就是说,在原型继承阶段,用户还不能决定以什么参数来实例化构造函数;
- 使用不够灵活。用户需要在原型声明阶段实例化父类对象,但是很多时候我们无法确定父类对象实例化的时机和场所;
- prototype属性固有的副作用。