JS中的OOP

JS中的OOP

OOP 为我们解决了什么问题?想象一下,我们希望为教师提供一个平台,每位注册的教师都可以提交分数,并为课程分配作业和其他内容。

如果有一个地方(在本例中是一个对象),可以访问所有教师的数据(例如他们的姓名、职业和班级列表)以及前面提到的那些功能,那就太好了。简而言之,就是将数据和方法封装或者捆绑在一起。

为了实现我们的目的,我们创建一个函数来接收教师的数据并返回一个包含这些数据的对象以及每个教师能够执行的方法。

const teacherCreator = (name: string, profession: string, classes: string[]) => {const newTeacher = {};newTeacher.name = name;newTeacher.profession = profession;newTeacher.classes = classes;newTeacher.submitMark = function(mark: number, studentId: number) {//....console.log(`学生${studentId} 的分数是${mark}`)}newTeacher.assignHomework = function(homework: string, classId: number) {// ....}
}

这是我们的teacherCreator功能演示。通过这种方式,我们实现了数据和方法的封装。但有一个问题值得我们考虑。

内存耗用大

假设我们在有 1000 名教师,我们的这些消耗内存方法会在每个教师对象中重复定义。

但是我们只想要一份函数副本。将所有方法都初始化在一个地方,并且每当我们尝试调用其中任何一个方法时,我们都从那里选择它并避免这种重复,这不是更有效吗?

我们可以在 JavaScript 中通过多种解决方案完成同样的事情。

方法一:工厂函数

我们可以将实现teacherCreator函数的方式更改为:

const teacherCreator = (name: string, profession: string, classes: string[]) => {const newTeacher = Object.create(teacherFunctionStore);newTeacher.name = name;newTeacher.profession = profession;newTeacher.classes = classes;// 返回一个对象return newTeacher;
}// 创建一个对象包含所有方法
const teacherFunctionsStore = {submitMark: function(mark: number, studentId: number) {//....console.log(`学生${studentId} 的分数是${mark}`)},assignHomework: function(homework: string, classId: number) {// ....}
}const teacher1 = teacherCreator('Leo', 'English', ['A1-English']);
teacher1.assignHomeWork('do workbook', 10)

在上面的代码块中,我们不会在每个教师对象上创建这些方法。我们只是有一个地方——另一个对象——来存储所有方法。现在的问题是 JavaScript 如何知道在哪里找到这些方法并执行它们。

JavaScript 如何执行这段代码?

下面我们将逐步指导如何在所有方法中执行此代码。一般来说,在 JavaScript 中执行时,每段代码所发生的情况都是完全相同的。

在这里插入图片描述

  1. JavaScript 会在全局内存中看到teacherCreator,它将把它创建为一个函数。顺便说一下,它不会进入函数内部。
  2. 接下来,它将看到我们的teacherFunctionStore对象,并使用其中的方法在全局内存中启动它。
  3. 代码的下一行是一个名teacher1为的变量,它将在全局内存中初始化,但尚未设置值。因此,JavaScript 将进入teacherCreator执行上下文中的函数内部。
  4. 在执行上下文内部 -每个函数调用都会创建一个新的执行上下文- 首先是将函数的参数设置在该执行上下文的本地内存中。
  5. Object.create()将为我们创建一个空对象。我们已经将teacherFunctionStore 传递给了它,因此它将使用该对象__proto__的属性来引用newTeacher对象。该参考在图中用红线突出显示。
const newTeacher = Object.create(teacherFunctionStore);
  1. 然后,我们将向对象添加属性并将其返回到全局内存中——设置teacher1的值。

JavaScript 现在如何调用这些方法?

现在的问题是teacher1.assignHomework()如何执行。这些方法不在对象本身内。

答案是非常清楚的。当我们调用对象的方法时,JavaScript 将首先查看该对象以查找该函数。如果找到它,它将执行它。在我们的例子中,它在我们的teacher1对象上找不到assignHomework。它应该抛出错误吗?当然不是。至少现在还不行。

JavaScript 不会很快放弃。如果属性或方法不在对象本身内部,它将在对象的__proto__属性中查找。

我们已经知道,我们的对象teacher1会通过__proto__链接到teacherFunctionStoreJavaScript会找到其中的方法并执行它。

方法2:构造函数

使用new关键字来实现我们的功能,该关键字可以自动为我们完成这些链接工作。

function TeacherCreator(name: string, profession: string, classes: string[]) {this.name = name;this.profession = profession;this.classes = classes;
}TeacherCreator.prototype.submitMark = function(mark: number, studentId: number) {//....console.log(`学生${studentId} 的分数是${mark}`)
},TeacherCreator.prototype.assignHomework = function(homework: string, classId: number) {// ....
}const teacher1 = new TeacherCreator('Leo', 'English', ['A1-English']);
teacher1.assignHomeWork('do workbook', 10)

TeacherCreator构造函数前面的 new 关键字将为我们自动执行两件事:

  • 创建一个新的教师对象
  • 返回新创建的教师对象

构造函数如何使用 new 关键字在幕后执行?

在这里插入图片描述

  1. 第一行是定义TeacherCreator构造函数。JavaScript 中的每个函数也是一个对象。因此,这里我们有一个函数-对象组合,如上图所示。每当我们想要访问函数部分时,我们都使用()符号,而对于对象,我们使用.符号。
  2. 在接下来的代码行中,我们将在对象TeacherCreator部分的原型对象上设置一些方法,而不是其函数内。
  3. 我们在全局内存中定义一个teacher1常量。在执行上下文中执行函数之前我们不知道它的值。
  4. 在执行上下文中,首先要处理的还是函数参数。
  5. new关键字将为我们做的所有事情都以蓝色列出。
  6. 创建了包含给我们的函数的数据的对象。对象会在new关键字的帮助下自动this设置__proto__prototype对象。
  7. 现在,this返回的teacher1对象将是最终值,并且该执行上下文将被关闭。
  8. 这里调用我们创建的对象上的方法。JavaScript 将首先查找teacher1对象上的assignHomwork方法。它进入teacher1__proto__对象,但没有找到它,但 __proto__链接到prototype对象并在那里找到它并执行该函数。

ES6 class

class关键字语法的作用与前面方法中TeacherCreator构造函数的作用完全相同。然而,它给我们带来了编写更快代码的好处,并且看起来与其他语言中实现的 OOP 类似。

class TeacherCreator {constructor(name, profession, classes){this.name = name;this.profession = profession;this.clasess = clasess;}// methods that will be accessible in prototype later on:submitMark = function(mark: number, studentId: number) {//....console.log(`学生${studentId} 的分数是${mark}`)},assignHomework = function(homework: string, classId: number) {// ....}
}

ES6 类是否改变了迄今为止 OOP 的实现方式?

尽管我们的代码现在看起来更加清晰易读,但幕后的整个原理仍然是一样的。JavaScript 仍然会为我们的TeacherCreator类创建函数-对象组合。类内部的constructor方法与我们在构造函数方法中的组合中的函数相同。

总之,重复相同的过程,但变得更加自动化和干净。这是 JavaScript OOP 背后的一般过程,基本上是原型继承。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/212749.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android keylayout键值适配

1、通过getevent打印查看当前keyevent数字对应事件和物理码 2、dumpsys input 查看输入事件对应的 KeyLayoutFile: /system/usr/keylayout/Vendor_6080_Product_8060.kl 3、通过物理码修改键值映射,修改/system/usr/keylayout/目录下的文件

Docker可视化管理界面工具Portainer安装

Portainer是Docker容器管理界面工具,可以直观的管理Docker。 部署也很简单: 官方安装文档地址 1、创建数据卷 docker volume create portainer_data2、下载允许容器 docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restartalways -v /v…

归并排序算法

文章目录 归并排序一、归并排序思路二、归并排序算法模板三、题目代码 归并排序 一、归并排序思路 二、归并排序算法模板 void merge_sort(int q[], int l, int r) {if (l > r) return;int mid l r >> 1;//中间值merge_sort(q, l, mid);merge_sort(q, mid 1, r);…

程序环境和预处理(详解版)

我们已经学到这里,这就是关于C语言的最后一个集中的知识点了,虽然它比较抽象,但是了解这部分知识,可以让我们对C代码有更深层次的理解,知道代码在每一个阶段发生什么样的变化。让我们开始学习吧! 目录 1.程序的翻译环…

Flutter学习(四)如何取消listview的越界效果

背景 在flutter的开发过程中,ListView是很常见的一个组件,但是,由于ListView的某些自带的体验,导致不太好的用户体验。例如ListView中,滑动到顶部或者底部的时候,再次滑动,会有越界的效果&…

C语言——从键盘输人一个表示年份的整数,判断该年份是否为闰年,并显示判断结果。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int year 0;printf("请输入年份&#xff1a;");scanf("%d",&year);if((year%4 0) && (year%100!0) || (year%400 0)){printf("%d是闰年\n",year);}else{p…

Python+jieba+wordcloud实现文本分词、词频统计、条形图绘制及不同主题的词云图绘制

目录 序言&#xff1a;第三方库及所需材料函数模块介绍分词词频统计条形图绘制词云绘制主函数 效果预览全部代码 序言&#xff1a;第三方库及所需材料 编程语言&#xff1a;Python3.9。 编程环境&#xff1a;Anaconda3&#xff0c;Spyder5。 使用到的主要第三方库&#xff1a;…

GeoTrust SSL数字安全证书介绍

一、GeoTrust OV证书的介绍 GeoTrust OV证书是由GeoTrust公司提供的SSL证书&#xff0c;它是一种支持OpenSSL的数字证书&#xff0c;具有更高的安全性和可信度。GeoTrust是全球领先的网络安全解决方案提供商&#xff0c;为各类用户提供SSL证书和信任管理服务。GeoTrust OV证书…

Ps:参考线

参考线 Guides用于帮助精确地定位图像或元素&#xff0c;显示为浮动在图像上的非打印线&#xff0c;可以移动或移除&#xff0c;还可以临时锁定。 Ps 中的参考线可分为三大类&#xff1a;画布参考线、画板参考线和智能参考线。 可在“首选项/参考线、网格和切片”中设置参考线的…

【nlp】3.2 Transformer论文复现:1. 输入部分(文本嵌入层和位置编码器)

Transformer论文复现:输入部分(文本嵌入层和位置编码器) 1 输入复现1.1 文本嵌入层1.1.1 文本嵌入层的作用1.1.2 文本嵌入层的代码实现1.1.3 文本嵌入层中的注意事项1.2 位置编码器1.2.1 位置编码器的作用1.2.2 位置编码器的代码实现1.2.3 位置编码器中的注意事项1 输入复现…

【管理运筹学】背诵手册(五)| 动态规划

五、动态规划 基本概念 阶段&#xff08;Stage&#xff09;&#xff1a;将所给问题的过程&#xff0c;按时间或空间特征分解成若干相互联系的阶段&#xff0c;以便按次序去求解每阶段的解&#xff0c;常用字母 k k k 表示。 状态&#xff08;State&#xff09;&#xff1a;…

深度解析 Docker Registry:构建安全高效的私有镜像仓库

文章目录 什么是Docker Registry&#xff1f;Docker Hub vs. 私有RegistryDocker Hub&#xff1a;私有Registry&#xff1a; 如何构建私有Docker Registry&#xff1f;步骤一&#xff1a;安装Docker Registry步骤二&#xff1a;配置TLS&#xff08;可选&#xff09;步骤三&…