、ES5 有 6 种方式可以实现继承,分别为:
1.原型链继承
原型链继承的基本思想是利用原型让一个引用类型继承,另一个引用类型的属性和方法。
缺点:
1、通过原型来实现继承时,原型会变成另一个类型的实例,原先的实例属性变成了现在的原型属性,该原型的引用类型属性会被所有的实例共享。
2、在创建子类型的实例时,没有办法在不影响所有对象实例的情况下给超类型的构造函数中传递参数。
2.借用构造函数
在子类型的构造函数中调用超类型构造函数
优点:
1、可以向超类传递参数
2、解决了原型中包含引用类型值被所有实例共享的问题
缺点:
1、方法都在构造函数中定义,函数复用无从谈起,另外超类型原型
中定义的方法对于子类型而言都是不可见的。
3.组合继承(原型链 + 借用构造函数) 实现多个继承
在子类构造函数中 调用父类构造函数,并通过 call 改变 this 的指向 ,继承了父类的属性
通过 new 一个父类的实例作为子类构造函数的原型prototype ,原型链方式来继承父类的方法
使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,既通过在原型上定义方法来实现了函数复用,又保证了每个实例都有自己的属性
缺点:
1、无论什么情况下,都会调用两次超类型构造函数:一次是在创建
子类型原型的时候,另一次是在子类型构造函数内部。
优点:
1、可以向超类传递参数
2、每个实例都有自己的属性
3、实现了函数复用
4.原型式继承
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
缺点:
同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
5.寄生式继承
创建一个仅用于封装继承过程的函数, 该函数在内部已某种方式来增强对象,最后再像真地是它做了所有工作一 样返回对象。
缺点:
1、使用寄生式继承来为对象添加函数,会由于不能做到函数复用而效率低下。
2、同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
6.寄生组合式继承
不必为了指定子类型的原型而调用超类型的构造函数,我们需要的仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。
优点:
只调用了一次超类构造函数,效率更高。避免在 SuberType.prototype
上面创建不必要的、多余的属性,与其同时,原型链还能保持不变。因此寄生组合继承是引用类型最理性的继承范式。
7.es6继承
代码量少,易懂
//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People{
constructor(name='wang',age='27'){
this.name = name;
this.age = age;
}
eat(){
console.log(`${this.name} ${this.age} eat food`)
}
}
//继承父类
class Woman extends People{
constructor(name = 'ren',age = '27'){
//继承父类属性
super(name, age);
}
eat(){
//继承父类方法
super.eat()
}
}
let wonmanObj=new Woman('xiaoxiami');
wonmanObj.eat();
ES5继承和ES6继承的区别:
es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中
Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this)
es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this