JS继承的六种方式
构造继承
通过使用call、apply方法可以在新创建的对象上执行构造函数,用父类的构造函数来增加子类的实例,以此实现继承。
具体实现:
优点:简单明了,直接继承超类构造函数的属性和方法
缺点:在子实例中会拷贝父类构造函数中的方法,当子类很多的时候,会增加内存的占用量,并且当实例需要改变方法的时候,之前的实例都无法及时更新,无法继承原型链上的属性和方法
原型链继承
利用原型链来实现继承,超类的一个实例作为子类的原型,声明一个过渡的函数对象,将传入的需要继承的函数赋值给过渡函数的对象
具体实现:
当c访问b的superSpeak属性的时候,会先在c的实例属性中查找,没有找到,之后到b的原型即a的实例中去找,还是没有找到,继续到a的原型对象中找。
优点:
实例是子类的实例,实际上也是父类的一个实例
父类新增原型方法/原型属性,子类都能访问到
缺点:
所有子类的实例的原型都共享一个超类实例的属性和方法,无法实现多继承
虽然原型上任何类型的属性值都不会通过实例被重写,但是引用类型的属性值可能会受到影响。
比如:
组合继承
利用构造继承和原型链组合
具体实现:
优点:解决了构造继承和原型链继承的两个问题
缺点:实际上子类上会拥有超类的两个属性(上图的第12行和第15行),多占用了一点儿内存,只是子类的属性覆盖了超类的属性
原型式继承
采用原型式继承并不需要定义一个类,本质上是浅拷贝,以一个对象为模板复制出新的对象所以引用的数据共享在不同的实例间。
具体实现:
当d修改引用对象时,e的数据也会发生变化。
多用于不构建构造函数,仅仅模拟一个对象的时候。
优点:直接通过一个对象生成一个继承该对象的对象
缺点:不是类式继承,而是原型式基础,缺少了类的概念
寄生式继承
创建一个仅仅用于封装继承过程的函数,然后在内部以某种方式增强对象,最后返回对象
具体实现:
优点:把原型式继承再次封装,然后在对象上扩展新得方法,再把新对象返回
缺点:依旧没有类的概念
寄生组合式继承
结合寄生式继承和组合式继承,完美实现不带两份超类属性的继承方式
具体实现:
优点:完美实现继承,解决了组合式继承带两份属性的问题
缺点:过于繁琐,因此组合继承更好一些
哈哈哈,未完待续...