在面向对象语言中,继承有两种形式:1.接口继承; 2.实现继承。在js中只有实现继承。
利用原型链来实现继承,基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。
代码如下:
function superClass (){
this.property1 = true;
}
superClass.prototype.method1 = function (){
console.log("superClass method1");
}
superClass.prototype.method2 = function (){
console.log("superClass method2");
}
function subClass (){
this.property2 = false;
}
subClass.prototype = new superClass();
subClass.prototype.method1 = function (){
console.log("subClass method1");
}
subClass.prototype.method3 = function () {
console.log("subClass method3");
}
var superclass = new superClass ();
superclass.method1(); //superClass method1
superclass.method2(); //superClass method2
var subclass = new subClass ();
subclass.method1(); //subClass method1
subclass.method2(); //superClass method2
subclass.method3(); //subClass method3
上面的例子中subClass继承了superClass中的method1 和method2 两个方法,并且重写了method1方法。增加了自己的method3 方法。
subClass 继承的时候其实是重写了原型对象,使prototype指向了superClass 的一个实例。
原来存在与superclass的实例中的属性和方法,现在也存在与subClass.prototype中。
即:原来在superClass中为实例属性和方法,现在为subClass中为原型属性和方法。
他们的关系如图:
上面的代码我们并没有使用 subClass 默认提供的原型,而是给它换成了一个新的原型。这个原型就是 superClass 的一个实例。
于是新的原型就有了 superClass 的实例所拥有的所有的属性和方法。而且内部还有一个指针指向了superClass 的原型。
最终的结果是:subclass 指向了 subClass 的原型,subClass 的原型指向了 superClass 的原型。 method2 方法还是存在于 superClass 方法中。但是 property1 存在于 subClass.prototype 中。这是因为 property1 是一个实例属性而 method2 为原型方法。
在 superClass 中的 method1 不能被 subclass 访问到,是因为原型的搜索机制导致的。
原型机制的搜索机制为:每当读取某个对象的属性或者方法的时候,都会先搜索实例中是否有该属性或者方法,如果没有继续搜索原型中的属性或者方法,如果还是没有则继续向下搜索,直到 Object。所以 subClass.prototype 中的 method1 覆盖了 superClass.prototype 中的 method1 。
原型链的问题:
在原型链中出现了一个问题,就是本来在父类中为实例属性和方法,在继承类中却变成了原型属性和方法。例如上面的property1。
解决这个问题需要使用原型链和构造函数组合的办法,即组合继承或者伪经典继承。