javascript手动实现继承

前言

如果没有class的话,js实现手动继承的方式有很多,其中有很多简单能用的,也有不太好用,这里介绍一个比较常见到的寄生组合继承的实现方式

当然更厉害的可以尝试直接更细腻的模拟js的class或者其他编程语言的class,写出更完整的继承效果,到那里篇章更复杂更难理解了细节多到数不胜数(例如很多语法糖的处理),这里只介绍原型相对比较常见的利用原型实现写法

手动实现继承

我们利用现有原型天然的支持继承效果,也就是调用函数时会从函数到原型查找方法,找不到会将原型看做对象,继续找其构造函数的原型,向上调用直到原型为空结束

也就是我们要做的实际上也就是,更方便的将继承效果在创建子类的时候,一键挂载关联到子类

实现大概有下面几个步骤:

  1. 直接将父原型给子原型,那么他们会共享,也不太符合原型的调用链,出现公用混乱问题
  2. 因此采用新建寄生对象的方式,创建一个新的原型对象(寄生对象),将父类的原型赋予寄生对象原型上,寄生对象的构造函数指向子类,将子对象的原型指向寄生对象,这样寄生对象成功伪装成我们的新子类了
  3. 子类初始化的时候可根据情况调用父类构造函数避免出现属性丢失问题,使用callback无缝调用
  4. 父子类建立关联后,在扩展子原型链条,相当于在给我们的寄生对象扩展属性,也就没有侵入到父原型了

ps:直接new Parent()给子原型不挺好,这样相当于多调用了一次父构造函数,看起来比较多余,且构造内容多的话,也可能会间接导致子原型函数出现了不该出现的函数(且返回内容为空)

js 复制代码
//寄生对象
function objectFactory(prototype) {
  function F() {}
  F.prototype = prototype;
  return new F();
}
//寄生对象化作继承者
function createAssociation(Children, Parent) {
  const prototype = objectFactory(Parent.prototype);
  prototype.constructor = Children;
  Children.prototype = prototype;
}
//父类函数
function Parent(name) {
  this.name = name;
}
Parent.prototype.getMyName = function() {
  return `name:${this.name}`;
}
//子类函数
function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}
//父子建立关联,此时子原型会被覆盖,注意顺序
createAssociation(Child, Parent);
//开始扩展子原型
Child.prototype.getMyAge = function() {
  return `age:${this.age}`;
}

const child1 = new Child('child1', 10);
const child2 = new Child('child2', 20);
console.log(child1.getMyName()); // name:child1
console.log(child1.getMyAge()); // age:10
console.log(child2.getMyName()); // name:child2
console.log(child2.getMyAge()); // age:20

就这样我们实现了继承

最后

如果让你实现一个带 super 的效果,你该怎么实现呢,有什么思路么(当然不必非得一样😄)

相关推荐
沧沧凉凉12 分钟前
两个小时,AI 把我 2018 年那个 Unity 版保卫萝卜搬进了浏览器
前端·游戏·ai编程
薄雾晚晴25 分钟前
大模型Skill暴论:所有Skill终将消亡?最新Skill方法论与模型增强开发实战
前端·后端·架构
绝世唐门三哥25 分钟前
Git - git stash 语法演进与实战指南
前端·git
神膘护体小月半42 分钟前
mask 渐变遮罩属性
前端·css·css3
梨想橙汁1 小时前
Webpack 快速上手:前端工程化、打包原理、从零搭建基础项目
前端·webpack·前端工程化
zhanghaha13141 小时前
HTML系列教程:12_HTML 表格 <table> 零基础详解
前端·html
Betterme1 小时前
Vue3 竞态请求防护组合式hooks:useLatestRequest 设计思路
前端
_zhourui_h_1 小时前
一个 [ECS] 到底生成了多少代码?EasyECS 最核心的秘密都在这里
前端
梨想橙汁1 小时前
Git 分支详解:创建切换、合并分支、冲突解决实战
前端·git
雪芽蓝域zzs1 小时前
Vue3 defineProps` / `defineEmits` 是编译器宏,不需要手动 import 导入
前端·javascript·vue.js