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.pswp.cn/news/165799.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165799.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165799.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python編寫的爬蟲為什么受歡迎?

每每回想起我當初學習python爬蟲的經歷,當初遇到的各種困難險阻至今都歷歷在目。即便當初道阻且長,窮且益堅,我也從來沒有想過要放棄。今天我將以我個人經歷,和大家聊一聊有關Python語音編寫的爬蟲的事情。談一談為什么最近幾年py…

C#中的事件(委托的發布和訂閱、事件的發布和訂閱、EventHandler類、Windows事件)

目錄 一、委托的發布和訂閱 1.訂閱操作符號“"和取消訂閱操作符號“-” 2.示例源碼 二、事件的發布和訂閱 三、EventHandler類 四、Windows事件 C#中的事件是指某個類的對象在運行過程中遇到的一些特定事情,而這些特定的事情有必要通知給這個對象的使用者…

【海德教育】河北初級職稱報名條件:

河北助理工程師 學歷要求 大專畢業后滿3年,工程類專業 本科畢業后滿1年 ,工程類專業 非工程類專業,年限增加2年即可。

多線程,線程池,線程的創建,線程池的參數

文章目錄 多線程-1 高并發〇、使用多線程的場景1. 為什么使用多線程 1. 線程概述1.1 線程和進程1.2 并發和并行1.3 多線程的優勢1.4 程序運行原理1.5 主線程 1.6 線程的 6 種狀態2. 線程的創建和啟動2.1 Thread類2.2創建線程有哪幾種方法2.2.1 繼承**Thread**類,重寫…

centos7 安裝docker

1.卸載舊版本,不管裝沒裝過,執行一下,防止版本沖突 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine 2. yum安裝gcc相關 以及 安…

electron27-react-mateos:基于electron+react18仿matePad桌面系統

基于Electron27React18ArcoDesign搭建桌面版OS管理系統。 electron-react-mateos 基于最新前端跨端技術棧electron27.xreact18arco-designzustand4sortablejs構建的一款仿制matePad界面多層級路由管理OS系統。 ElectronReactOS支持桌面多路由配置,新開窗口彈窗開啟路…

YB4051系列設備是高度集成的 Li-lon 和 Li-Pol 線性充電器,針對便攜式應用的小容量電池。

YB4051H 300mA 單電池鋰離子電池充電器0.1 mA 終端,45nA 電池漏電流 概述: YB4051系列設備是高度集成的 Li-lon 和 Li-Pol 線性充電器,針對便攜式應用的小容量電池。它是一個完整的恒流/恒壓線性充電器。不需要外部感應電阻,由于…

51單片機利用I/O口高阻狀態實現觸摸控制LED燈

51單片機利用I/O口高阻狀態實現觸摸控制LED燈 1.概述 這篇文章介紹使用I/O口的高阻狀態實現一個觸摸控制LED燈亮滅的實驗。該實驗通過手觸摸P3.7引腳,改變電平信號控制燈的亮滅。 2.實驗過程 2.1.實驗材料 名稱型號數量單片機STC12C20521LED彩燈無1晶振12MHZ1電…

Elasticsearch:ES|QL 函數及操作符

如果你對 ES|QL 還不是很熟悉的話,請閱讀之前的文章 “Elasticsearch:ES|QL 查詢語言簡介???????”。ES|QL 提供了一整套用于處理數據的函數和運算符。 功能分為以下幾類: 目錄 ES|QL 聚合函數 AVG COUNT COUNT_DISTINCT 計數為近…

geemap學習筆記013:為遙感動態GIF圖添加圖名

前言 遙感動態GIF圖可以展示地理區域隨時間的變化,這對于監測自然災害、濕地變化、城市擴展、農田變化等方面非常有用,并且可以反復觀察圖像,以更深入地了解地表的動態變化。本節主要是對遙感動態GIF圖添加圖名,以便于更好地理解…

聚觀早報 |一加12正式開啟預訂;OPPO Reno11系列賣點

【聚觀365】11月24日消息 一加12正式開啟預訂 OPPO Reno11系列賣點 小鵬第三季度營收財報 Claude 2.1 聊天機器人公布 現代汽車將與倫敦大學學院合作 一加12正式開啟預訂 全新的一加12系列公開亮相已有一段時間,不久前一加官方宣布,該機將于12月4日…

android:The application could not be installed: INSTALL_FAILED_TEST_ONLY

1、問題描述 在android12 (OPPO PEEM00)上安裝APP時,提示上述異常 原因分析: android:testOnly:應用是否是為了測試,它可能向外暴露數據,引發安全漏洞。因此國內廠商的手機檢測到這個屬性為t…

ebpf實戰(一)-------監控udp延遲

問題背景: 為了分析udp數據通信中端到端的延遲,我們需要對整個通信鏈路的每個階段進行監控,找出延遲最長的階段. udp接收端有2個主要路徑 1.數據包到達本機后,由軟中斷處理程序將數據包接收并放入udp socket的接收緩沖區 數據接收流程 2. 應用程序調用recvmsg等a…

<JavaEE> 什么是進程控制塊(PCB Process Control Block)?

目錄 一、進程控制塊的概念 二、進程控制塊的重要屬性 2.1 唯一身份標識(PID) 2.2 內存指針 2.3 文件描述符表 2.4 狀態 2.5 優先級 2.6 記賬信息 2.7 上下文 一、進程控制塊的概念 進程控制塊(Process Control Block, PCB&#xff…

Springboot引入分布式搜索引擎Es RestAPI

文章目錄 RestAPI初始化RestClient創建索引庫刪除索引庫判斷索引庫是否存在總結 RestClient操作文檔增加文檔數據查詢文檔刪除文檔修改文檔批量導入文檔小結 RestAPI ES官方提供了各種不同語言的客戶端,用來操作ES。這些客戶端的本質就是組裝DSL語句,通…

IOS Frida 常用腳本

調用堆棧 console.log("bt:" + Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join(\n\t)); Hook 調用,修改返回值 // Get a reference to the openURL selectorvar openURL = ObjC.classes.UIApplication["- openURL:&qu…

uni-app 跨端開發注意事項

文章目錄 前言H5正常但App異常的可能性標題二H5正常但小程序異常的可能性小程序正常但App異常的可能性小程序或App正常,但H5異常的可能性App正常,小程序、H5異常的可能性使用 Vue.js 的注意區別于傳統 web 開發的注意H5 開發注意微信小程序開發注意支付寶…

Docker實用篇

Docker實用篇 0.學習目標 1.初識Docker 1.1.什么是Docker 微服務雖然具備各種各樣的優勢,但服務的拆分通用給部署帶來了很大的麻煩。 分布式系統中,依賴的組件非常多,不同組件之間部署時往往會產生一些沖突。在數百上千臺服務中重復部署…

STM32入門筆記15_PWR電源管理模塊

PWR和低功耗模式 PWR簡介 PWR(Power Control) 電源控制PWR負責管理STM32內部的電源供電部分,可以實現可編程電壓檢測器和低功耗模式的功能可編程電壓檢測器(PVD) 可以監控VDD電源電壓,當VDD下降到PVD閾值以下或上升到PVD閾值之上時,PVD會觸…

C++學習之路(一)什么是C++?如何循序漸進的學習C++?【純干貨】

C是一種高級編程語言,是對C語言的擴展和增強。它在C語言的基礎上添加了面向對象編程(OOP)的特性,使得開發者能夠更加靈活和高效地編寫代碼。 C的名字中的“”符號表示在C語言的基礎上向前發展一步,即“加加”&#x…