emmmm……
一般使用混合式继承。
es5
在子类的构造方法中通过用call方法执行父类的构造方法可以使子类继承父类的共有属性。
原型方法的继承会涉及到原型和原型链。
如果直接将子类的原型指向父类的原型,会导致一个问题:扩展子类的原型方法时父类的原型方法也会被扩展。
一般采用一个空对象作为媒介。
将子类构造方法的原型指向一个用new关键词定义的父类的新实例。这个实例是一个空对象。则调用该实例某方法时一定会沿原型链查找到该实例的构造方法,父类的原型方法因此会被继承。此时修改子类的原型并不会对父类的原型方法造成污染。因为子类构造方法的原型指向父类的实例而并不指向父类构造方法的原型。
这种原型方法的继承也有一个问题:每次继承的操作都会创建一个父类的空对象。这是不够完善的,相对完善的方法很多书里都有,我用的少。
es6
使用相关的class和extends语法
class 子类 extends 父类
在构造方法constructor中,有且必须有super方法。它会调用父类的constructor函数并创建一个执行环境(excicute context)递给子类使用。
super方法的调用和this的引用有明确的先后顺序。在constructor中,如果在super方法被调用前调用了this指针,将会在子类进行实例化操作的时候抛出错误。
super对象可以在子类的方法中被引用。
在子类普通的方法中,super指向父类的原型,如果在子类中调用super对象上的方法,this将指向子类,这是es6的规定。
在静态方法中,super对象指向父类。
class定义的类的静态方法我没有使用过,这种方法由static关键词在类的内部定义,不会被实例继承的方法,可能与es5的私有方法类似。
ps:以上介绍的继承方法在继承浏览器原生的Date类时,es6表现良好,es5会在实例化后调用方法时报错,es6+label转成es5的代码同样也会报错。主要原因是调用的实例对象不再是Date的实例,可以手动修改继承类的prototype(Object.setPropertyOf())。