【JS很简单】——继承

103 阅读1分钟

原型链继承

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() {}