1.原型链继承
function Super(name) {
this.name = name;
}
Super.prototype.getSuperValue = function() {
return this.name;
}
function Sub(age) {
this.age = age;
}
Sub.prototype.getSubValue = function() {
return this.age;
}
Sub.prototype = new Super();
let instance = new Sub();
这种方式有一个弊端 Sub.prototype(Super-instance)实例上的属性和方法被Sub的所有实例共享同一份数据
原型链示意图
2.盗用函数
function Super(name) {
this.name = name;
}
function Sub(...args) {
Super.call(this, ...args);
}
盗用函数解决了Sub实例共享Super实例数据问题,但是没有Super继承原型上的属性和方法
3.组合继承
function Super(name) {
this.name = name;
}
function Sub(...args) {
Super.call(this, ...args);
}
const superInstance = new Super();
superInstance.constructor = Sub;
Sub.prototype = superInstance;
这里要说的是实例属性上面是没有构造函数属性的,他拿的是原型对象上的构造函数,我们在设置构造函数原型对象属性的时候,要把原型对象的构造属性改成当前构造函数;
上面通过原型链继承结合盗用构造函数,
1.解决了原型链继承Super实例(Sub.prototype)属性,方法共享的数据的问题
是通过盗用构造函数在Sub实例上对Super实例(Sub.prototype)属性,方法进行覆盖
但是有一个问题Super函数调用两次.
1. Super.call(this, ...age)
2. new Super()
4.原型式继承
function inhert(obj) {
function F() {};
F.prototype = obj;
return new F();
}
这类似于原生Object.create()的实现,他在作用在于不用声明类型,通过方法也能继承。使用场景是既可以拿到以前的数据,又可以覆盖之前的数据,不影响之前的对象数据。但跟原型链继承同一个通病,数据共享的问题。
5.寄生式继承
function factory(obj) {
const instance = inhert(obj);
instance.getSubValue = function() {
console.log('sub');
}
}
寄生式继承不过是使用工厂函数在原型式继承上面增强罢了
6.寄生式组合继承
function Super(name){
this.name = name;
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
function merge(Sub, Super) {
const superInstance = inhert(Super.prototype);
superInstance.constructor = Sub;
Sub.prototype = superInstance;
}
这样就解决了两次Super调用的问题。
以上是ES5的继承
7.ES6 class继承
class Super {
constructor(name){
this.name = name;
}
getSuperValue(){
console.log('super')
}
}
class Sub extends Super {
constructor(name, age){
super(name);
this.age = age;
}
getSubValue() {
console.log('sub');
}
}
简单又方便
上述继承方式源自于红宝书