聊聊JavaScript中实现继承的6种方法

javascriptjavascript 2023-08-28 23:21:44 900
摘要: 面试官:“你说说JavaScript中实现继承有哪几种方法?”紧张的萌新:“额,class中用extends实现继承,然后...没了...”面试官:“...”······想必绝大部分人一说继承就会想到类中的继承吧,但其实继承可不是class的...

面试官:“你说说 JavaScript 中实现继承有哪几种方法?”

紧张的萌新:“额,class 中用 extends 实现继承,然后...没了...”

面试官:“...”

······

想必绝大部分人一说继承就会想到类中的继承吧,但其实继承可不是 class 的专利,本文将总结,JavaScript 中关于继承的几种方案,其中包括原型链,盗用构造函数、组合式等等,助你力压面试官。

注意:本文比较适合具备一定 JS 进阶基础的同学(不会也没关系,收藏就会了?),涉及知识点有:原型、原型链、构造函数、this指向等。如果文中有不对、疑惑的地方,欢迎在评论区留言指正?

0. 继承

继承是面向对象编程中讨论最多的话题。很多面向对象语言都支持两种继承:接口继承和实现继承。前者只继承方法签名,后者继承实际的方法。 接口继承在 ECMAScript中 是不可能的,因为函数没有签名。实现继承是 ECMAScript 唯一支持的继承方式,而这主要是通过原型链实现的。

1. 原型链继承【方案一】

ECMA-262 把原型链定义为 ECMAScript 的主要继承方式。其基本思想就是通过原型继承多个引用类型的属性和方法。重温一下构造函数、原型和实例的关系:

  • 每个构造函数都有一个prototype属性指向原型对象
  • 所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数

而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应的另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。这就是原型链的基本构想。

实现原型链继承涉及如下代码模式

// 定义 Person 构造函数
function Person() {
  this.name = 'CoderBin'
}

// 给 Person 的原型上添加 getPersonValue 方法(原型方法)
Person.prototype.getPersonValue = function() {
  return this.name
}

// 定义 Student 构造函数
function Student() {
  this.sno = '001'
}

// 继承 Person — 将 Peson 的实例赋值给 Student 的原型
Student.prototype = new Person()

Student.prototype.getStudentValue = function() {
  return this.sno
}

// 实例化 Student
let stu = new Student()

console.log(stu.getPersonValue()) // CoderBin

1.1 代码解读