ECMAScript继承的多种方式一

38 阅读2分钟

一、原型链继承

原理:使用父级构造函数的实例对象重写子级构造函数的的原型对象来实现继承

function Person() {
  this.property = true
}
Person.prototype.getProperty = function () {
  return this.property
}
function Child() {
  this.childProperty = false
}
Child.prototype = new Person() // Person实例对象重写Child原型对象实现继承
Child.prototype.getChildProperty = function () {
  return this.childProperty
}
const child = new Child()
console.log(child.property) // true
console.log(child.getProperty()) // true

缺点1:父类构造函数是引用类型时,引用值会在所有实例对象之间共享

function Person() {
    this.colors = ['red', 'blue', 'green']
}
function Child() {}
Child.prototype = new Person()
let child1 = new Child()
child1.colors.push('gray')
console.log(child1.colors) // ['red', 'blue', 'green', 'gray']
let child2 = new Child()
console.log(child2.color) // ['red', 'blue', 'green', 'gray']

缺点2:子类构造函数不能直接向父类构造函数传递参数

为了解决原型链继承的引用问题和传参问题,使用“经典继承”来解决这个问题

二、经典继承

原理:在子类构造函数中调用父类构造函数,并使用call或apply,指定父类构造函数中的this为子类实例对象。

function Person() {
    this.colors = ['red', 'blue', 'green']
}
function Child() {
    Person.call(this) // 相当于在Child的实力对象上运行了所有Person中的初始化代码
} 
const child1 = new Child()
child1.colors.push('gray')
console.log(child1.colors) // ['red', 'blue', 'green', 'gray']
const child2 = new Child()
console.log(child2.colors) // ['red', 'blue', 'green']

经典继承可以给父类构造函数传参

function Person(name) {
    this.name = name
}
function Child() {
    Person.call(this, 'Mary')
    this.age = 12
}
const instance = new Child()
console.log(instance.name) // 'Mary'

缺点:方法不能共用,每次实例化一个对象的时候还是需要重新给对象添加方法,无法继承父类构造函数的原型上的方法

结合原型继承和经典继承,可以解决这个问题

三、组合继承

原理:在经典继承的基础上,实例化父类构造函数重写子类原型对象

function Person(name) {
    this.name = name
    this.colors = ['red', 'blue', 'green']
}
Person.prototype.sayName = function () {
    return this.name
}
function Child(name, age) {
    Person.call(this, name)
    this.age = 12
}
Child.prototype = new Person()
Child.prototype.sayAge = function() {
    return this.age
}

const child1 = new Child('Tom', 12)
child1.colors.push('gray')
console.log(child1.colors) // ['red', 'blue', 'green', 'gray']
console.log(child1.sayName()) // 'Tom'
console.log(child1.sayAge()) // 12

const child2 = new Child('Mary', 22)
console.log(child2.colors) // ['red', 'blue', 'green']
console.log(child2.sayName()) // 'Mary'
console.log(child2.sayAge()) // 22