JS基础⚡️ 探究JS的六种继承

JavaScript中,相比于传统的面向对象编程语言使用类(class)来实现继承关系,JS的做法是利用原型对象(prototype)来实现继承。虽然在 ES6 中引入了class语法,但实质上该语法仍然基于原型继承实现(语法糖)。

今天让我们来学习下六种继承的方式

第一种 原型链的继承

js 复制代码
function Person() {
  this.name = 'Person'
}
Person.prototype.eating = function () {
  console.log(this.name + 'eating~')
}
// 子类:特有属性和方法
function Student() {
  this.sno = 111
}
const p = new Person()
Student.prototype = p
Student.prototype.studying = function () {
  console.log(this.name + ' studying~')
}
const stu = new Student()
console.log(stu.name) // Person
stu.eating() // Person eating~
stu.studying() // Person studying~

弊端有很多

1.第一个弊端:打印stu对象,继承的属性是看不到的

2.直接修改对象上的属性,是给本对象添加了一个新属性 获取引用,修改引用中的值,会相互影响

3.第三个弊端:在前面实现类的过程中都没有传递参数

第二种 借用构造函数继承

js 复制代码
function Person(name, age, friends) {
  this.name = name
  this.age = age
  this.friends = friends
}
Person.prototype.eating = function () {
  console.log(this.name + ' eating~')
}
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends)
  this.sno = 111
}
const p = new Person()
Student.prototype = p
Student.prototype.studying = function () {
  console.log(this.name + ' studying~')
}
const stu = new Student('Student', 18, ['kobe'], 111)
console.log(stu.name)  // Student
stu.eating() // Student studying~
stu.studying()//Student eating~

原型链继承的弊端基本解决

但是借用构造函数也会有自己的弊端:

1.第一个弊端: Person函数至少被调用了两次

2.第二个弊端: stu的原型对象上会多出一些属性, 但是这些属性是没有存在的必要

第三种 组合继承

js 复制代码
function Person(name, age, friends) {
  this.name = name
  this.age = age
  this.friends = friends
}
Person.prototype.eating = function () {
  console.log(this.name + ' eating~')
}
//子类
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends)
  this.sno = 111
}
// 直接将父类的原型赋值给子类, 作为子类的原型
// 直接将 Person.prototype 赋值给 Student.prototype 会导致 Student.prototype 和 Person.prototype 指向同一个对象,因此对 Student.prototype 的修改也会影响到 Person.prototype,因此使用`Object.create` 来创建一个新的对象,并将其赋值给 `Student.prototype`,以保持继承关系的正确性
Student.prototype = Object.create(Person.prototype)
Student.prototype.studying = function () {
  console.log(this.name + ' studying~')
}
const stu = new Student('student', 18, ['friend'], 111)
console.log(stu) // Person { name: 'student', age: 18, friends: [ 'friend' ], sno: 111 }
stu.eating() // student eating~

组合继承结合了原型链继承和构造函数继承的优点。首先使用构造函数继承来继承父对象的属性,然后将父对象的原型赋值给子对象的原型,实现对父对象原型上方法的继承。

第四种 原型式继承

js 复制代码
let obj = {
  name: 'why',
  age: 18
}
let info = Object.create(obj)
console.log(info)
console.log(info.__proto__)

弊端

1.原型链继承多个实例的引用类型属性指向相同。修改引用中的值,会相互影响。

2.无法传递参数

第五种 寄生式继承

js 复制代码
let personObj = {
  running: function () {
    console.log('running')
  }
}
function createStudent(name) {
  let stu = Object.create(personObj)
  stu.name = name
  stu.studying = function () {
    console.log('studying~')
  }
  return stu
}

let stuObj = createStudent('why')
let stuObj1 = createStudent('kobe')
let stuObj2 = createStudent('james')

弊端与原型式继承一样

1.原型链继承多个实例的引用类型属性指向相同。修改引用中的值,会相互影响。

2.无法传递参数

第六种 寄生组合式继承

js 复制代码
//将SubType的原型对象指向SuperType的原型对象
function inheritPrototype(SubType, SuperType) {
  SubType.prototype = Object.create(SuperType.prototype)
// 重新定义 SubType 的 constructor 属性
 Object.defineProperty(SubType.prototype,'constructor',{
    enumerable: false,
    configurable: true,
    writable: true,
    value: SubType
  })
}
function Person(name, age, friends) {
  this.name = name
  this.age = age
  this.friends = friends
}
Person.prototype.running = function () {
  console.log('running~')
}
function Student(name, age, friends, sno, score) {
  Person.call(this, name, age, friends)
  this.sno = sno
  this.score = score
}
inheritPrototype(Student, Person)
Student.prototype.studying = function () {
  console.log('studying~')
}
let stu = new Student('student', 18, ['xiaoming'], 111, 100)
console.log(stu)
stu.studying()
stu.running()
console.log(stu.constructor.name)

这个方法比较成熟 前面继承方式弊端基本解决 只调用一次父类构造函数 Child可以向Parent传参 父类方法可以复用 父类的引用属性不会被共享 ES6中的类继承extends也是使用寄生组合继承原理

文章更多作为个人学习,有错欢迎指出,也希望对你有所帮助

相关推荐
Larcher12 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐25 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭37 分钟前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程