神族九帝's blog 神族九帝's blog
首页
  • 神卡套餐 (opens new window)
  • 神族九帝 (opens new window)
  • 网盘资源 (opens new window)
  • 今日热点 (opens new window)
  • 在线PS (opens new window)
  • IT工具 (opens new window)
  • FC游戏 (opens new window)
  • 在线壁纸 (opens new window)
  • 面试突击
  • 复习指导
  • HTML
  • CSS
  • JavaScript
  • 设计模式
  • 浏览器
  • 手写系列
  • Vue
  • Webpack
  • Http
  • 前端优化
  • 项目
  • 面试真题
  • 算法
  • 精选文章
  • 八股文
  • 前端工程化
  • 工作笔记
  • 前端基础建设与架构 30 讲
  • vue2源码学习
  • 剖析vuejs内部运行机制
  • TypeScript 入门实战笔记
  • vue3源码学习
  • 2周刷完100道前端优质面试真题
  • 思维导图
  • npm发包
  • 重学node
  • 前端性能优化方法与实战
  • webpack原理与实战
  • webGl
  • 前端优化
  • Web3
  • React
  • 更多
  • 未来要做的事
  • Stirling-PDF
  • ComfyUI
  • 宝塔面板+青龙面板
  • 安卓手机当服务器使用
  • 京东自动评价代码
  • 搭建x-ui免流服务器(已失效)
  • 海外联盟
  • 好玩的docker
  • 收藏夹
  • 更多
GitHub (opens new window)

神族九帝,永不言弃

首页
  • 神卡套餐 (opens new window)
  • 神族九帝 (opens new window)
  • 网盘资源 (opens new window)
  • 今日热点 (opens new window)
  • 在线PS (opens new window)
  • IT工具 (opens new window)
  • FC游戏 (opens new window)
  • 在线壁纸 (opens new window)
  • 面试突击
  • 复习指导
  • HTML
  • CSS
  • JavaScript
  • 设计模式
  • 浏览器
  • 手写系列
  • Vue
  • Webpack
  • Http
  • 前端优化
  • 项目
  • 面试真题
  • 算法
  • 精选文章
  • 八股文
  • 前端工程化
  • 工作笔记
  • 前端基础建设与架构 30 讲
  • vue2源码学习
  • 剖析vuejs内部运行机制
  • TypeScript 入门实战笔记
  • vue3源码学习
  • 2周刷完100道前端优质面试真题
  • 思维导图
  • npm发包
  • 重学node
  • 前端性能优化方法与实战
  • webpack原理与实战
  • webGl
  • 前端优化
  • Web3
  • React
  • 更多
  • 未来要做的事
  • Stirling-PDF
  • ComfyUI
  • 宝塔面板+青龙面板
  • 安卓手机当服务器使用
  • 京东自动评价代码
  • 搭建x-ui免流服务器(已失效)
  • 海外联盟
  • 好玩的docker
  • 收藏夹
  • 更多
GitHub (opens new window)
  • 面试突击

  • 复习指导

  • HTML

  • CSS

  • JavaScript

  • 设计模式

  • 浏览器

  • 手写系列

    • 继承
      • 原型链继承
      • 构造函数继承(借助 call)
      • 组合继承(Object.create)
      • 原型式继承
      • 寄生组合式继承
      • ES6 的 extends 关键字
      • 参考
    • call,apply,bind
    • 手写promise
    • 手写基础js
    • 手写排序
    • 并行限制的Promise
  • Vue

  • Webpack

  • Http

  • 前端优化

  • 项目

  • 面试真题

  • 算法

  • 精选文章

  • 八股文

  • 前端工程化

  • 面试题
  • 手写系列
wu529778790
2021-09-06

继承

20210906152341

通过 Object.create 来划分不同的继承方式,最后的寄生式组合继承方式是通过组合继承改造之后的最优继承方式,而 extends 的语法糖和寄生组合继承的方式基本类似

# 原型链继承

function Parent() {
  this.name = "parent";
  this.play = [1, 2, 3];
}

function Child() {
  this.type = "child";
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;
console.log(new Child());

缺点:公用一个原型对象

# 构造函数继承(借助 call)

function Parent() {
  this.name = "parent";
  this.getName = function() {
    return this.getName;
  };
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child() {
  Parent.call(this);
  this.type = "child";
}

console.log(new Child());

缺点:只能继承父类的实例属性和方法,不能继承原型属性或者方法

# 组合继承(Object.create)

function Parent() {
  this.name = "parent";
  this.play = [1, 2, 3];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child() {
  Parent.call(this);
  this.type = "child";
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

const s1 = new Child();
const s2 = new Child();
s1.play.push(4);

console.log(s1.play, s2.play);
console.log(s1.getName());
console.log(s2.getName());

20210906150920

缺点: parent 执行了两次:第一次是改变 child 的 prototype 的时候,第二次是通过 call 方法调用 Parent 的时候

上面介绍的更多是围绕着构造函数的方式,那么对于 JavaScript 的普通对象,怎么实现继承呢?

# 原型式继承

这里不得不提到的就是 ES5 里面的 Object.create 方法,这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数)。

Object.create是浅拷贝

let parent4 = {
  name: "parent4",
  friends: ["p1", "p2", "p3"],
  getName: function() {
    return this.name;
  },
};

let person4 = Object.create(parent4);
person4.name = "tom";
person4.friends.push("jerry");

let person5 = Object.create(parent4);
person5.friends.push("lucy");

console.log(person4.name);
console.log(person4.name === person4.getName());
console.log(person5.name);
console.log(person4.friends);
console.log(person5.friends);

# 寄生组合式继承

function Parent() {
  this.name = "parent";
  this.play = [1, 2, 3];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child() {
  Parent.call(this);
  this.type = "child";
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

# ES6 的 extends 关键字

class Person {
  constructor(name) {
    this.name = name;
  }
  // 原型方法
  // 即 Person.prototype.getName = function() { }
  // 下面可以简写为 getName() {...}
  getName = function() {
    console.log("Person:", this.name);
  };
}

class Gamer extends Person {
  constructor(name, age) {
    // 子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
    super(name);
    this.age = age;
  }
}
const asuna = new Gamer("Asuna", 20);
asuna.getName(); // 成功访问到父类的方法

bable 把 ES6 的代码翻译成 ES5 之后

function _possibleConstructorReturn(self, call) {
  // ...
  return call && (typeof call === "object" || typeof call === "function")
    ? call
    : self;
}

function _inherits(subClass, superClass) {
  // 这里可以看到
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,

      enumerable: false,

      writable: true,

      configurable: true,
    },
  });
  if (superClass)
    Object.setPrototypeOf
      ? Object.setPrototypeOf(subClass, superClass)
      : (subClass.__proto__ = superClass);
}

var Parent = function Parent() {
  // 验证是否是 Parent 构造出来的 this
  _classCallCheck(this, Parent);
};

var Child = (function(_Parent) {
  _inherits(Child, _Parent);
  function Child() {
    _classCallCheck(this, Child);
    return _possibleConstructorReturn(
      this,
      (Child.__proto__ || Object.getPrototypeOf(Child)).apply(this, arguments)
    );
  }
  return Child;
})(Parent);

# 参考

  • https://t1.lagounews.com/KR50RXRDsI6F8 (opens new window)

3d467cff7d26d2abdb58dea74114855

编辑 (opens new window)
上次更新: 2025/03/17, 12:21:00
地址栏URL回车
call,apply,bind

← 地址栏URL回车 call,apply,bind→

最近更新
01
Code Review
10-14
02
ComfyUI
10-11
03
vscode插件开发
08-24
更多文章>
Power by vuepress | Copyright © 2015-2025 神族九帝
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×