继承
1.原型链继承
1 | function SuperType() { |
原型链继承:将上级构造函数的实例赋值给下级构造函数的原型
缺点:如果继承属性有引用类型值,多个实例容易被篡改
1 | function SuperType() { |
2.借用构造函数继承
1 | function SuperType(){ |
创建子类实例时调用SuperType
构造函数,于是SubType
的每个实例都会将SuperType中的属性复制一份
缺点:
只能继承父类的实例属性和方法,不能继承原型属性/方法
无法实现复用,每个子类都有父类实例函数的副本,影响性能
3.组合继承
1 | function SuperType(name){ |
缺点:
父级构造函数会被调用两次,里面的属性会被写入子级实例和他的原型中,出现重复和冗余
4.原型式继承
1 | function object(obj){ |
缺点:
原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
无法传递参数
ES5 Object.create 的模拟实现
5.寄生式继承
1 | function object(obj){ |
6.寄生组合式继承
1 | function inheritPrototype(subType, superType){ |
7.ES6 extends
1 | class Rectangle { |
extends
继承的核心代码如下,其实现和上述的寄生组合式继承方式一样
1 | function _inherits(subType, superType) { |
总结
1、函数声明和类声明的区别
函数声明会提升,类声明不会。首先需要声明你的类,然后访问它,否则像下面的代码会抛出一个ReferenceError。
1 | let p = new Rectangle(); |
2、ES5继承和ES6继承的区别
- ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.call(this)).
- ES6的继承有所不同,实质上是先创建父类的实例对象this,然后再用子类的构造函数修改this。因为子类没有自己的this对象,所以必须先调用父类的super()方法,否则新建实例报错。