Skip to content

继承

[toc]

js
  // ES5 原型链继承
  function Super(name, age) {
    this.name = name
    this.age = age
    console.log('调用一次')
  }
  Super.prototype.say = function() {
    console.log('I am ' + this.name)
  }

  function Sub(name, age, sex) {
//     Super.call(this, name, age)
    this.sex = sex
  }

  Sub.prototype = new Super() // new 设置原型指向时,参数未知

//   Sub.prototype = Object.create(Super.prototype)
//   Sub.prototype.constructor = Sub

  let ch = new Sub('jack', 12, 1)
  ch.say() // say 方法在原型链上
  // I am undefined
js
  // 手写组合式继承

  // ES5 原型链 + 借用构造函数继承
  // 父类构造函数在设置原型指向 new 时冗余执行一次
  function Super(name, age) {
    this.name = name
    this.age = age
    console.log('调用一次')
  }
  Super.prototype.say = function() {
    console.log('I am ' + this.name)
  }

  function Sub(name, age, sex) {
    Super.call(this, name, age)
    this.sex = sex
  }

  Sub.prototype = new Super() // new 设置原型指向时,参数未知

//   Sub.prototype = Object.create(Super.prototype)
//   Sub.prototype.constructor = Sub

  let ch = new Sub('jack', 12, 1)
  ch.say()
  // I am undefined
js
  // ES5 寄生组合式继承
  function Super(name, age) {
    this.name = name
    this.age = age
    console.log('调用一次')
  }
  Super.prototype.say = function() {
    console.log('I am ' + this.name)
  }

  function Sub(name, age, sex) {
    Super.call(this, name, age)
    this.sex = sex
  }

  Sub.prototype = Object.create(Super.prototype) // 创建父类副本,替代创建父类实例,带来问题是,构造器指向了父类
  Sub.prototype.constructor = Sub // 修正

  let ch = new Sub('jack', 12, 1)
  ch.say()

原型链

构造函数、原型、实例的关系

  1. 每一个构造函数都有一个原型对象 fn.prototype = object
  2. 原型对象都包含一个指向构造函数的指针 obj.proto
  3. 实例对象都包含一个指向原型对象的内部指针 obj.proto
实例对象 (内部指针 __proto__)
   --> 构造函数 (prototype)
    --> 原型对象
      --> chain

原型链继承

形式

js
Sub.prototype = new Super() // new 设置原型指向时,参数未知

原型链实现继承的本质是重写原型对象

问题:

  1. 包含引用类型值的原型属性会被所有实例共享
  2. 不能向超类构造函数传参
Sub.prototype = new Super() // new 设置原型指向时,参数未知

借用构造器函数

在子类内部生成自己的属性,不同子类互不干扰

原型式继承

Object.create() 相当于

js
function object(o) {
  function F(){} // 临时构造器函数
  F.prototype = o
  return new F()
}

本质是浅复制,依然存在引用污染问题(原型方式都存在)

与其它继承差异,这是对象直接生成对象

寄生式继承

基于原型式继承,增强对象

参考《高级程序设计》

Prototypal inheritance

js
// {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null

属性遮蔽、函数覆盖

JS | 前端进阶之道

组合继承

原型链 + 借用构造函数

最常用

父类构建函数调用两次 new + call

寄生组合式继承

解决组合继承调用两次问题

js
function inheritPrototype(sub, parent) {
  const obj = Object.create(parent.prototype); // 创建父类原型的副本
  obj.constructor = sub; // 将副本的构造函数指向子类
  sub.prototype = ob; // 将该副本赋值给子类的原型
}

JavaScript 七大继承全解析