作者:myprelude@github
原文链接: https://myprelude.github.io
转载请注明出处,保留原文链接和作者信息。
继承是js的中比较重要的知识点,也是面试中的必考点,我们在日常开发中无时无刻都在和它打交道,我们今天就来聊一聊继承这个话题。
首先构建我们的父类function People(name){
this.name = name;
this.like = ['working','speak'];
}
People.prototype.say = function(){
console.log(`我的名字是${this.name}`)
}
原型链继承
function Man(name){
this.name = name;
}
Man.prototype = new People('xiaoming');
Man.prototype.constructor = Man;
const instance = new Man('xiaowang');
console.log(instance.name) // xiaowang
instance.say() // 我的名字时xiaowang
instance.like.push('sleep')
console.log(instance.like) // ['working','speak','sleep']
const instance1 = new Man('chengcheng');
console.log(instance1.name) // chengcheng
instance.say() // 我的名字时xchengcheng
console.log(instance1.like) // ['working','speak','sleep']
- 优点:简单;实例即是父类的实例也是子类实例。
- 缺点:所有实例共享原型上引用属性;无法向父类构造函数传参。
构造继承(apply,call)
function Man(){
People.apply(this,arguments)
}
const instance = new Man('mingming');
instance.like.push('sleep');
console.log(instance.like) // ['working','speak','sleep']
console.log(instance.name) // mingming
const instance1 = new Man('chengcheng');
console.log(instance1.like) // ['working','speak']
console.log(instance1.name) // chengcheng
console.log(instance.say()) // Uncaught TypeError: instance1.say is not a function
- 优点:简单;解决子类向父类传参的问题,解决父类引用属性共享问题
- 缺点:实例对象并不是父类的实例;不能调用父类原型上的方法。
组合继承
function Man(){
People.apply(this,arguments)
}
Man.prototype = new People();
Man.prototype.constructor = Man;
const instance = new Man('xiaowang');
console.log(instance.name) // xiaowang
instance.say() // 我的名字时xiaowang
instance.like.push('sleep')
console.log(instance.like) // ['working','speak','sleep']
const instance1 = new Man('chengcheng');
console.log(instance1.name) // chengcheng
instance.say() // 我的名字时xchengcheng
console.log(instance1.like) // ['working','speak']
- 优点:解决子类向父类传参的问题,解决父类引用属性共享问题,解决调用父类原型方法和属性问题。
- 缺点:因为父类构造函数被执行了两次,子类的原型对象(Man.prototype)中也有一份父类的实例属性(name),而且这些属性会被子类实例(instance,instance1)的属性覆盖掉(即通过instance.name访问不到Man.prototype上的name属性),也存在内存浪费。
组合寄生继承
function Man(){
People.apply(this,arguments)
}
// 组合继承的缺点就是在继承父类方法的时候调用了父类构造函数,从而造成内存浪费,
// 现在只要解决了这个问题就完美了。那在复用父类方法的时候,
// 使用Object.create方法也可以达到目的,没有调用父类构造函数,问题解决。
Man.prototype = Object.create(People.prototype);
// 当然这个地方也可以使用Object.setPrototypeOf(Man.prototype, People.prototype)
Man.prototype.constructor = Man;
- 优点:完美解决上面所有问题。Es6 class extends 通过babel解析成 组合寄生继承。
- 缺点:。。。。