持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情
原型继承
原型继承:让子类实例的原型等于父类的实例
优点:实例可继承:实例的构造函数的属性,父类构造函数属性,父类原型的属性
缺点:
- 子类实例无法像父类构造函数传参
- 子类实例共享属性,造成实例间的属性会相互影响
function Parent() {
this.num = ['1']
this.addNum = function () {
this.num.push('2')
}
}
function Child() {
}
Child.prototype = new Parent()
var child1 = new Child()
var child2 = new Child()
var parent = new Parent()
child1.addNum()
console.log(child1.num, child2.num) // [ '1', '2' ] [ '1', '2' ]
console.log(child1.addNum === child2.addNum) // true
构造函数
构造函数:继承用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制)
优点:子类实例可以向父实例传参,可以继承多个构造函数属性
缺点:
- 父类的方法没有被共享,造成内存浪费
- 只继承父类构造函数的属性,没有继承父类原型的属性
function Parent() {
this.num = ['1']
this.addNum = function () {
this.num.push('2')
}
}
function Child() {
Parent.call(this)
}
var child1 = new Child()
var child2 = new Child()
child1.addNum()
console.log(child1.num, child2.num) // [ '1', '2' ] [ '1' ]
console.log(child1.addNum === child2.addNum) // false
组合继承
组合继承:组合原型链继承和借用构造函数继承
优点:可以继承父类原型上的属性,可以传参,可复用
缺点:父类构造函数被调用两次,子类实例的属性存在两份。造成内存浪费
function Parent() {
this.num = ['1']
}
Parent.prototype.addNum = function() {
this.num.push('2')
}
function Child() {
Parent.call(this)
}
Child.prototype = new Parent()
var child1 = new Child()
var child2 = new Child()
child1.addNum()
console.log(child1.num, child2.num) // [ '1', '2' ] [ '1' ]
console.log(child1.addNum === child2.addNum) //true
寄生继承
完美:子类都有各自的实例不会相互影响,且共享了父类的方法
function Parent() {
this.num = ['1']
}
Parent.prototype.addNum = function() {
this.num.push('2')
}
function Child() {
Parent.call(this)
}
Child.prototype = Object.create(Parent.prototype)
var child1 = new Child()
var child2 = new Child()
child.addNum()
console.log(child1.num, child2.num) //[ '1','2' ] [ '1' ]
console.log(child1.addNum === child2.addNum) //true
ES6 class
和寄生继承实现的效果一致
class Parent {
constructor() {
this.num = ['1']
}
addNum() {
this.name.push('2')
}
}
class Child extends Parent {
constructor() {
super()
}
}
var child1 = new Child()
var child2 = new Child()
child1.addNum()
console.log(child1.num, child2.num) // [ '1', '2' ],['2']
console.log(child1.addNum === child2.addNum)
总结
对比以上几个demo,通过打印两个子类实例的num属性,判断子类实例是否相互影响,通过打印两个子实例的addNum方法是否相等,可以判断是否共享了父类方法,从而更好的体现以上几种继承方法的优缺点,让我们在开发中能更合理的选择哪种继承方法进行使用开发。