JS-六种继承方式(ES5+ES6)

63 阅读2分钟

前五种为ES5继承实现,最后一种ES6

一、原型链继承

原理:让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承

image.png 缺点: 由于所有Child实例原型都指向同一个Parent实例,引用类型的私有属性公有化了, 因此对某个Child实例的父类引用类型做变量修改会影响所有的Child实例

在创建子类实例时无法向父类的构造函数传参(没有 super 功能)

二、构造函数继承

原理:子类的构造函数中执行父类的构造函数,并为其绑定子类的 this,让父类的构造函数把成员属性和方法都挂到子类的 this 上去,这样既能避免实例之间共享一个原型实例,又能向父类构造方法传参

image.png 缺点:继承不到父类原型上的方法(所以不能单独使用咯 ~)

三、组合继承

原理:使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性(构造函数+原型对象

image.png 组合式继承的缺点:每次创建子类实例都执行了两次构造函数(Parent.call() 和 new Paren()),虽然这并不影响对父类的继承,但子类创建实例时,原型中会存在两份相同的属性和方法,这并不优雅

四、寄生式继承

原理:创建一个实现继承的函数,改函数内部以某种形式来增强对象,最后返回对象

image.png 缺点:类似构造函数继承,会导致函数难以重用

五、寄生式组合继承(最理想)

为了解决第三种继承提到的构造函数被执行两次的问题, 我们将指向父类实例改为指向父类原型, 减去一次构造函数的执行

image.png

但这种方式存在一个问题,由于子类原型和父类原型指向同一个对象,我们对子类原型的操作会影响到父类原型,例如给 Child.prototype 增加一个getName()方法,那么会导致 Parent.prototype 也增加或被覆盖一个 getName 方法,为了解决这个问题,我们给 Parent.prototype 做一个浅拷贝

image.png

最后不要忘了把方法封装一下哦!

image.png

六、ES6的class实现继承

原理:ES6类 + 寄生式组合继承

详细讲解请看ES6中面向对象第五点-类的继承

image.png