继承是很多OO语言中都支持的,基本上都支持两种继承方式:接口继承和实现继承。接口继承只继承方法名,实现继承则继承实际的方法。ECMAScript中无法实现接口继承,只支持实现继承的方式,这主要是依靠原型链来实现的。
原型链实现继承的主要方式,是利用原型让一个引用类型继承另一个引用类型的属性和方法。实现原型链有一种基本模式,其代码大致如下:
这里我们可以看到定义了两个类型SuperType和SubType,SubType继承SuperType的方式是将SuperType的实例对象赋值给了SubType的原型上,实现的本质是重写了SubType的原型对象,带之以一个新类型的实例。SubType的prototype现在被赋值为SuperType的实例对象,SuperType的实例对象中的__proto__指向的是SuperType的原型对象,SuperType的原型对象中又有指针指向的是SuperType的构造函数,这样SubType的prototype最终也会指向SuperType的原型对象,这样就完成了原型链继承。但是记住,所有函数的默认原型都是Object的实例。
如何确定原型和实例之间的关系?
我们可以通过两种方式进行却,第一种是利用instanceof操作符,利用它可以测试实例和原型链中出现的构造函数,结果是返回true,例如:
第二种是利用isPrototypeOf(),只要原型链中出现过的原型,都可以说是该原型链派生的实例的原型,同样的也会返回TRUE:
使用原型链进行继承确实很方便,但是不免会出现一些问题,问题之一就是包含引用类型值得原型,因为包含引用类型值得原型属性会被所有实例共享,所以之前我们说属性需要定义在构造函数中,而不是定义在原型上面,但是通过原型进行继承,原型实际会变成另一个类型的实例,于是原先的实例属性也就顺理成章的变成了现在的原型属性了。
如上可以看到,SuperType定义了一个构造函数,包含一个color属性(数组,引用类型),
SuperType的每个实例都会包含一个color属性,当SubType通过原型继承了SuperType的实例,实际上SubType.prototype也就成为了SuperType的一个实例,因此他也有了一个自己的color属性。但是结果是SubType的所有实例都会共享这一个color属性,所以看到后面对color的更改会反应到SubType的所有实例中。
问题二是创建子类型的实例时,不能向超类型的构造函数中传递参数,实际上应该是没有办法在不影响所有对象实例的情况下,给父类的构造函数传递参数。所以实践中很少会单独使用原型链。
网友评论