首页 > 其他分享 >关于js中继承的总结

关于js中继承的总结

时间:2024-12-04 23:12:04浏览次数:5  
标签:总结 function console name 继承 dog js prototype Man

继承

原型链继承

  • 通过原型链prototype实现的继承:将Man的prototype属性指向Person的实例对象
function Person(name) {
  this.name = 'Person'
  this.children = []
}
function Man() {
  this.sex = 'male'
}
Man.prototype = new Person()
Man.prototype.constructor = Man
const Tom = new Man()
const Jack = new Man()
Tom.children.push(2)
console.log(Tom.children) // [2]
console.log(Jack.children) // [2]
子类继承到的父类的引用数据类型指向同一个内存地址,是所有子类的实例化对象共用的,一个子类的实例化对象修改会造成别的实例化对象同一个属性的值改变

构造函数继承

  • 通过构造函数constructor实现的继承:在Man函数中调用Person构造函数并将Person函数的this指向Man中的this,即将构造函数Person中添加到this上的属性和方法添加到Man的this上
function Person(name) {
  this.name = name
}
Person.prototype.getName = function () {
  return this.name
}
function Man() {
  Person.call(this) // 将Person函数的this指向当前环境的this并执行Person函数
  this.sex = 'male'
}
let man = new Man('Tom')
console.log(man)
console.log(man.getName()) // 报错
子类只实现了对父类实例的属性和方法的继承,没有实现对父类原型属性和方法的继承

组合继承

  • 通过prototype和构造函数constructor实现的继承:在Man中需要调用Person.call(this),然后将Man的prototype指向Person的实例化对象,然后将Man.prototype.constructor指向Man,因为构造函数的原型对象上的constructor应该指回到其本身
function Person(name) {
  this.name = name
  this.children = [1]
}
Person.prototype.getName = function () {
  return this.name
}
function Man(name) {
  Person.call(this, name) // 首次执行
  this.sex = 'male'
}
Man.prototype = new Person() // 二次执行
Man.prototype.constructor = Man
let Tom = new Man('Tom')
let Jack = new Man('Jack')
Jack.children.push(2)
console.log(Jack.children) // [1,2]
console.log(Tom.children) // [1]
console.log(Jack.getName()) // Jack
console.log(Tom.getName()) // Tom
执行两次Person,多了性能开销

原型式继承

  • 通过Object.create实现的继承 Object.create()函数的参数为父类,Object.create()的返回结果为子类,实现了父类的属性在子类的[[prototype]]属性,即__proto__属性上,其中__proto__上没有constructor
let Man = {
  name: 'Man',
  children: [1],
  getName: function () {
    return this.name
  }
}
let Jack = Object.create(Man)
Jack.name = 'Jack'
Jack.children.push(2)
let Tom = Object.create(Man)
Tom.children.push(2, 3)
console.log(Jack.name) // Jack
console.log(Tom.name) // Man
console.log(Jack.name === Jack.getName()) // true
console.log(Jack.children) // [1,2,3,4]
console.log(Tom.children) // [1,2,3,4]
多个实例存在继承自Man对象的值为引用类型的数据指向同一个引用地址的问题

寄生式继承

  • 通过一个函数,扩展Object.create的结果实现的继承
let animal = {
  name: 'Animal',
  kinds: ['dog', 'cat'],
  getName: function () {
    return this.name
  }
}
function clone(other, name) {
  let clone = Object.create(other)
  clone.getKinds = function () {
    return this.kinds
  }
  clone.name = name
  return clone
}
let dog = clone(animal, 'dog')
console.log(dog.getName()) // dog
dog.kinds.push('pig')
console.log(dog.getKinds()) // ['dog', 'cat', 'pig']
在animal的基础上进行了clone的扩展,但是没有解决引用类型数据指向同一个地址的问题

寄生组合式集成

  • 寄生组合式继承,通过操作prototype和Object.create和扩展函数共同实现的继承
// 定义一个实现继承关系的方法
function clone(animal, kind) {
  kind.prototype = Object.create(animal.prototype)
  kind.prototype.constructor = kind
}
// 定义一个父类的构造函数,具有name和kinds属性
function Animal(name) {
  this.name = name
  this.kinds = ['dog', 'cat']
}
// 定义父类原型上的方法
Animal.prototype.getName = function () {
  return this.name
}
// 定义一个子类Dog的构造函数,继承自父类,同时传入对应的子类name值Dog,子类具有自己的kind属性dog
function Dog() {
  Animal.call(this, 'Dog')
  this.kind = 'dog'
}
// 用clone实现父类和子类之间的继承
clone(Animal, Dog)
// 定义子类原型上的的方法
Dog.prototype.getDogKind = function () {
  return this.kind
}
// 构造子类的实例
let dog = new Dog()
console.log(dog) // {name: 'Dog', kinds: ['dog', 'cat'], kind: 'dog', [[prototype]]: {constructor: function Dog(){}, getDogKind: function(){}, [[prototype]: {getName: function(){}, constructor: function(){},[[prototype]]: Object}]}}
console.log(dog.getName()) // Dog
console.log(dog.getDogKind()) // dog
解决了原型链继承和原型式继承,寄生原型式继承引用数据指向同一个位置的问题,同时克服了构造函数式继承中没有继承到父类原型对象上的方法和属性的问题。

extends关键字实现class继承

  • js引擎会在预编译阶段
class Animal {
  constructor(name) {
    this.name = name
    this.kinds = ['dog', 'cat']
  }
  getName() {
    return this.name
  }
}
class Dog extends Animal {
  constructor(name) {
    super(name)
    this.kind = 'dogs'
  }
  getDogKind() {
    return this.kind
  }
}
class Cat extends Animal {
  constructor(name) {
    super(name)
    this.kind = 'cats'
  }
  getCatKind() {
    return this.kind
  }
}
const dog = new Dog('dog')
const cat = new Cat('cat')
console.log(dog) // {name: 'dog',kinds: ['dog','cat'],kind: 'dogs',[[prototype]]: {constructor: class Dog{}, getDogKind: function(){}, [[prototype]: {getName: function(){}, constructor: class Anmial{},[[prototype]]: Object}]}}
console.log(cat) // {name: 'cat',kinds: ['dog','cat'],kind: 'cats',[[prototype]]: {constructor: class Cat{}, getCatKind: function(){}, [[prototype]: {getName: function(){}, constructor: class Anmial{},[[prototype]]: Object}]}}

extends关键字实现的继承,其最终结果是和寄生组合式继承一致的,通过babel编译之后也可以看出extends使用的就是寄生组合式继承。js继承模式中,寄生组合式继承是最优的一种继承模式了。

标签:总结,function,console,name,继承,dog,js,prototype,Man
From: https://www.cnblogs.com/shenhf/p/18587448

相关文章

  • 正则表达式总结-2
    转载:10个Python正则表达式文本搜索和替换技巧正则表达式(Regex)是处理文本的强大工具,尤其在Python中,通过re模块,我们可以灵活地进行搜索、匹配、替换等操作。下面,我们将深入浅出地介绍20个实用的Python正则表达式技巧,适合初学者逐步掌握,直到能够自信地运用到实际项目中。基本匹配......
  • 实验5 继承和多态
    1.实验任务1publisher.hpp1#pragmaonce23#include<iostream>4#include<string>56usingstd::cout;7usingstd::endl;8usingstd::string;910//Publisher11classPublisher{12public:13Publisher(conststring&s=......
  • linux ssd1307fb驱动适配总结
    linuxssd1307fb驱动适配总结linuxframebuffer点亮oled屏幕继第一篇文章,点亮了LED指示灯之后,正好手里有一个小模块,OLED显示屏。同样也是需要点亮的,那就继续点亮更多的东西吧。现在项目是越来越扣成本了,以前最少也是用一个彩色的串口屏,现在已经降级到使用黑白的OLED点阵......
  • 实验5 继承和多态
    3.pets.hpp#pragmaonce#include<iostream>#include<string>usingnamespacestd;classMachinePets{public:MachinePets(conststrings);virtualstringtalk()const=0;stringget_nickname();private:stringnickname;}......
  • 实验5 继承和多态
    实验任务3源代码:pets.hpp1#pragmaonce23#include<iostream>4#include<string>56usingnamespacestd;7classMachinePets{8public:9MachinePets(conststring&s);10stringget_nickname()const;11......
  • node.js毕设流浪猫狗救助系统 程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于流浪猫狗救助系统的研究,现有研究主要以动物保护的宏观理念及个别救助站的救助行为为主,专门针对流浪猫狗救助系统的研究较少。在国内外,动物保护意识......
  • node.js毕设教师工作量计算系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于教师工作量计算系统的研究,现有研究主要以整体教育管理系统为主,专门针对教师工作量计算系统的研究较少。在国内外教育领域不断发展的大环境下,学校规......
  • GIT 必知必会操作总结一
    GIT必知必会操作总结一相关B站视频链接,GeekHour一小时Git教程GIT简介GIT是一个开源的分布式版本管理系统,是Linux之父Torvalds为了帮助管理Linux内核开发而开发的一个版本控制软件它使用一个特殊的叫做仓库的数据库来记录文件的变化,仓库中每个文件都有一个......
  • 最新版Node.js下载安装及环境配置教程
    目录初识:Node.js一、下载:Node.js二、安装:Node.js1.下载【node.js】压缩包安装文件2.解压下载的安装包3.打开解压的【node-v22.11.0-x64】文件夹4.双击启动安装程序5.点击【Next】6.勾选【IacceptthetermsintheLicenseAgreement】,然后点击【Next】7.点击【Next......
  • 实验5 继承和多态
    实验任务3:task3.cpp:1#include<iostream>2#include<vector>3#include"pets.hpp"45voidtest(){6usingnamespacestd;78vector<MachinePets*>pets;910pets.push_back(newPetCats("miku"......