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也是使用寄生组合继承原理

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

相关推荐
清云随笔17 分钟前
axios 实现 无感刷新方案
前端
鑫宝Code18 分钟前
【React】状态管理之Redux
前端·react.js·前端框架
忠实米线26 分钟前
使用pdf-lib.js实现pdf添加自定义水印功能
前端·javascript·pdf
pink大呲花29 分钟前
关于番外篇-CSS3新增特性
前端·css·css3
少年维持着烦恼.33 分钟前
第八章习题
前端·css·html
我是哈哈hh36 分钟前
HTML5和CSS3的进阶_HTML5和CSS3的新增特性
开发语言·前端·css·html·css3·html5·web
田本初1 小时前
如何修改npm包
前端·npm·node.js
明辉光焱1 小时前
[Electron]总结:如何创建Electron+Element Plus的项目
前端·javascript·electron
牧码岛2 小时前
Web前端之汉字排序、sort与localeCompare的介绍、编码顺序与字典顺序的区别
前端·javascript·web·web前端