原型链继承
Vue 的很多方法就是这样实现的,像 _init
function Person(name){
this.name = name
}
Person.prototype.say = function(){
console.log(`my name is ${this.name}`)
}
硬找缺点,就是多个方法很麻烦,可以使用重写原型 👇
Person.prototype = {
constructor: Person,
say: function() {},
eat: function() {}
}
缺点:问题:函数自带的 constructor 是不可枚举,手动添加的 constructor 是可枚举的
原型继承
const a = {name: 'a'}
const b = Object.create(a)
Vue 在实现数组响应式时就用了该方法
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
构造函数继承
function Person (name) {
this.name = name
this.play = function() {}
}
Person.prototype.say = function() {}
function Child (name, age) {
Person.call(this, name)
this.age = age
}
Child.prototype.eat = function() {}
缺点:只能继承父类私有属性和方法,无法继承父类原型上的属性和方法
组合继承
function Person (name) {
this.name = name
this.play = function() {}
}
Person.prototype.say = function() {}
function Child (name, age) {
Person.call(this, name)
this.age = age
}
Child.prototype = new Person()
Child.prototype.constructor = Child
Child.prototype.eat = function() {}
可以继承父类私有属性和方法,也继承了父类原型上的属性和方法
缺点
- 两次调用了父类的构造函数
- 子类的原型链不干净
具体来讲就是 子类实例上有父类的私有属性和方法,子类的原型链上也有父类的私有属性和方法
寄生组合继承
function Person (name) {
this.name = name
this.play = function() {}
}
Person.prototype.say = function() {}
function Child (name, age) {
Person.call(this, name)
this.age = age
}
Child.prototype = Object.create(Person.prototype)
Child.prototype.constructor = Child
extends
ES6 的 class 本质上是 function 的语法糖,你看它们多像
class Person {
constructor(name) {
this.name = name
this.play = function() {}
}
}
Person.prototype.say = function() {}
class Child extends Person {
constructor(name, age) {
super(name)
this.age = age
}
}
Child.prototype.eat = function() {}