前端基礎:1-2 面向對象 + Promise

面向對象

對象是什么?為什么要面向對象?

通過代碼抽象,進而藐視某個種類物體的方式

特點:邏輯上遷移更加靈活、代碼復用性更高、高度的模塊化
對象的理解
  • 對象是對于單個物體的簡單抽象
  • 對象是容器,封裝了屬性 & 方法
    • 屬性:對象狀態
    • 方法:對象的能力 & 行為
//簡單對象
const O = {name:'zhangsan',changeName: name => `新的${name}`
}
//函數對象
function O(){this.name = '張三'this.changeName = name => `新的${name}`
}

構造函數 - 生成對象 => 實例

  • 需要一個模板
  • 類即對象模板
  • js本質并不是基于類,而是基于構造函數(創建對象的特殊函數)+原型鏈
function Course() {this.name = 'zhangsan';this.changeName = name => `新的${name}`
}
const course = new Course(args);

Course本質就是構造函數

  • 函數體內使用的this,指向要生成的實例
  • 生成對象用new來實例化
  • 可以初始化傳參
如果構造函數不初始化,可以使用具有相同功能嗎? --無法具有
如果在項目中需要使用,且不希望外界感知的情況下,如何拿到實例后的對象? => 單例模式 (編寫底層api代碼時,盡量做到不讓外部去感知區分內部類型)
function Course(){const _isClass = this instanceof Courseif(!_isClass){return new Course()}this.name = 'zhangsan'this.changeName = name => `新的${name}`
}
//使用
const course = Course()
思考:new是什么?/ new的原理? / new時候做了什么?
function Course(){}
const course = new Course()
  • 結構上:創建了一個空對象,作為返回的對象實例
  • 屬性上:將生成空對象的原型對象指向了構造函數的prototype屬性(course._ proto _=== Course.prototype)
  • 關系上:將當前對象實例賦給了內部的this
  • 生命周期上:執行了構造函數的初始化代碼
function usernew(obj,...args){const newObj = Object.create(obj.prototype)const result = obj.apply(newObj,args)return typeof result === 'object' ? result : newObj
}
追問:實例屬性影響 —— 獨立的
function Course(teacher, leader) {this.teacher = teacher;this.leader = leader;
}
const course1 = new Course('張三', '王五'); // course1.leader => 王五
const course2 = new Course('李四', '趙六'); // course2.leader => 趙六
course2.teacher = 'xxxx'; // course1.teacher => 李四
constructor是什么?
 function Course(teacher, leader) {this.teacher = teacher;this.leader = leader;}const course = new Course('張三', '李四');
  • 每個對象在創建時,會自動擁有一個構造函數屬性constructor

  • constructor源自原型對象,指向了構造函數的引用

  • 實例獲得了模版的屬性 => (大膽點)繼承了類的屬性

在這里插入圖片描述

繼承

js如何實現繼承

在原型對象的所有屬性方法,都可以被實例所共享
    function Game() {this.name = 'lol';}Game.prototype.getName = function() {return this.name;}// LOLfunction LOL() {};LOL.prototype = new Game();LOL.prototype.constructor = LOL;const game = new LOL();// 本質:重寫了原型對象方式,將父對象的屬性方法,作為自對象原型對象的屬性方法,同時重寫構造函數
追問:原型鏈直接繼承有什么缺點
    function Game() {this.name = 'lol';this.skin = ['s'];}Game.prototype.getName = function() {return this.name;}// LOLfunction LOL() {};LOL.prototype = new Game();LOL.prototype.constructor = LOL;const game1 = new LOL();const game2 = new LOL();game1.skin.push('ss');// 本質:重寫了原型對象方式,將父對象的屬性方法,作為自對象原型對象的屬性方法,同時重寫構造函數
    1. 父類屬性一旦賦值給到子類的原型屬性,此時屬性屬于子類的共享屬性了
    1. 實例化子類時,無法向父類進行傳參

解決方法:構造函數繼承

經典繼承:在子類的構造函數內部調用父類的構造函數
    function Game(arg) {this.name = 'lol';this.skin = ['s'];}Game.prototype.getName = function() {return this.name;}function LOL(arg) {Game.call(this, arg);}const game3 = new LOL('arg');// 解決了共享屬性問題 + 子向父傳參的問題

追問:原型鏈上的共享方法無法被讀取繼承,如何解決?

組合繼承
    function Game(arg) {this.name = 'lol';this.skin = ['s'];}Game.prototype.getName = function() {return this.name;}function LOL(arg) {Game.call(this, arg);}LOL.prototype = new Game();LOL.prototype.constructor = LOL;const game4 = new LOL('arg');

追問:組合繼承方式就沒有缺點嗎? 問題在于:無論何種場景,都會調用兩次父類的構造函數

解決方案:寄生組合繼承
    function Game(arg) {this.name = 'lol';this.skin = ['s'];}Game.prototype.getName = function() {return this.name;}function LOL(arg) {Game.call(this, arg);}LOL.prototype = Object.create(Game.prototype);LOL.prototype.constructor = LOL;const game5 = new LOL('arg');

拔高:如何實現多重繼承?

    function Game(arg) {this.name = 'lol';this.skin = ['s'];}Game.prototype.getName = function() {return this.name;}function Store() {this.shop = 'steam';}Game.prototype.getPlatform = function() {return this.shop;}function LOL(arg) {Game.call(this, arg);Store.call(this, arg);}LOL.prototype = Object.create(Game.prototype);Object.assign(Store.prototype,LOL.prototype);LOL.prototype.constructor = LOL;

瀏覽器原理

在這里插入圖片描述

Promise - 可以處理回調地獄

    1. promise狀態 - pending | fulfilled | rejected
      executor: new Promise的時候立即執行,接收兩個參數 resolve | reject
    1. promise默認狀態?狀態是如何流轉的? - 默認:pending 狀態流轉:pending => fufilled | pending => rejected
      內部維護成功value:undefined | thenable | promise
      內部維護失敗變量reason
    1. promise返回值? - then方法:接收onFulfilled 和 onRejected
      如果then時,promise已經成功,執行onFulfilled,參數value
      如果then時,promise已經失敗,執行onRejected,參數reson
      如果then中有異常,執行onRejected
Promise 方法
  1. Promise.all 全部執行完成
  2. Promise.race 有一個執行完成
手寫promise
    const PENDING = 'PENDING';const FULFILLED = 'FULFILLED';const REJECTED = 'REJECTED';class Promise {constructor(executor) {// 1. 默認狀態 - PENDINGthis.status = PENDING;// 2. 內部維護的變量值this.value = undefined;this.reason = undefined;// 成功的回調let resolve = value => {// 單向流轉if (this.status === PENDING) {this.status = FULFILLED;this.value = value;}}// 失敗的回調let reject = reason => {// 單向流轉if (this.status === PENDING) {this.status = REJECTED;this.reason = reason;}}try {executor(resolve, reject);} catch (error) {reject(error);}}then(onFulfilled, onRejected) {if (this.status === FULFILLED) {onFulfilled(this.value);}if (this.status === REJECTED) {onRejected(this.reason);}}}// 追問:異步怎么辦?const PENDING = 'PENDING';const FULFILLED = 'FULFILLED';const REJECTED = 'REJECTED';class Promise {constructor(executor) {// 1. 默認狀態 - PENDINGthis.status = PENDING;// 2. 內部維護的變量值this.value = undefined;this.reason = undefined;// 存放回調this.onResolvedCallbacks = [];this.onRejectedCallbacks = [];// 成功的回調let resolve = value => {// 單向流轉if (this.status === PENDING) {this.status = FULFILLED;this.value = value;this.onResolvedCallbacks.forEach(fn => fn());}}// 失敗的回調let reject = reason => {// 單向流轉if (this.status === PENDING) {this.status = REJECTED;this.reason = reason;this.onRejectedCallbacks.forEach(fn => fn());}}try {executor(resolve, reject);} catch (error) {reject(error);}}then(onFulfilled, onRejected) {if (this.status === FULFILLED) {onFulfilled(this.value);}if (this.status === REJECTED) {onRejected(this.reason);}if (this.status === PENDING) {// 存放隊列this.onResolvedCallbacks.push(() => {onFulfilled(this.value);});this.onRejectedCallbacks.push(() => {onRejected(this.reason);});}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/14355.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/14355.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/14355.shtml

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

相關文章

如何安裝 Docker

引言 - 介紹 Docker 技術的重要性和應用場景 - 簡要解釋 Docker 的工作原理和優勢 Docker 的安裝 Docker 在不同平臺上的安裝方法(Windows、Mac、Linux) Docker 是一個開源的容器化平臺,可以幫助開發人員和運維團隊更輕松地打包、交付和運行…

python 裝飾器 帶參數和不帶參數

裝飾器是Python語言中一種特殊的語法,用于在不修改原函數代碼的情況下,為函數添加額外的功能或修改函數的行為。通過裝飾器,我們可以在函數執行前后執行一些額外的代碼,或者修改函數的參數。 要使用裝飾器引入函數和參數&#xf…

Linux_應用篇(07) 系統信息與系統資源

在應用程序當中,有時往往需要去獲取到一些系統相關的信息,譬如時間、日期、以及其它一些系統相關信息,本章將向大家介紹如何通過 Linux 系統調用或 C 庫函數獲取系統信息, 譬如獲取系統時間、日期以及設置系統時間、日期等&#x…

restTemplate返回報文亂碼問題

默認服務端使用UTF8編碼 排查1&#xff1a; 請求前手動設置UTF-8編碼解析報文 RestTemplate restTemplate new RestTemplate(); restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); ResponseEntity<String> excha…

三能一體運營體系助力政企支撐水平提升

生產力的發展是現代社會孜孜不倦的追求&#xff0c;由此產生了我們熟悉的“機械化、電子化、信息化”乃至現今正在發生的“智能化”四次工業革命。這些是由技術的突破性發展帶來的&#xff0c;但我們也注意到生產力發展的另一個助力&#xff0c;即生產效率的提升&#xff0c;19…

【MySQL數據庫】mysql日志管理、備份與恢復

mysql日志管理、備份與恢復 MySQL數據庫備份及日志一、數據庫備份分類&#xff1a;如何選擇邏輯備份策略 (頻率)完全備份與恢復備份恢復 增量備份與恢復實現增量備份 基于時間點與位置恢復 二.MySQL日志管理 MySQL數據庫備份及日志 在生產環境中&#xff0c;數據的安全性是至關…

在未來你將何去何從?

在數字化的浪潮中&#xff0c;信息技術行業無疑是推動全球經濟和社會發展的重要動力。隨著科技的不斷迭代與進步&#xff0c;云計算、大數據、人工智能&#xff08;AI&#xff09;、物聯網&#xff08;IoT&#xff09;、5G通信和區塊鏈等技術已經深入到我們生活的每一個角落&am…

鴻蒙原生應用元服務開發-鴻蒙真機運行項目實戰與注意事項

一、解壓項目注意項目包不能為中文 二、用數據線將裝好DevEco Studio的電腦與設置為開發者模式的鴻蒙手機相連接。 三、將項目包托進DevEco Studio 中 注意項目包文件不能有嵌套 四、查看設備運行 五、點擊項目結構 六、勾選紅色框圈部分 登錄開發者賬號 七、選擇好公司 八、等…

我是如何使用 Next.js14 + Tailwindcss 重構個人項目的

前言 去年在學習 React 和 Nest 的時候&#xff0c;參考了大佬 imsyy 的項目 DailyHot&#xff0c;以此項目的靈感基于 React 開發&#xff0c;完成之后就沒怎么在意。 后來發現這個項目還有點小流量&#xff0c;每天差不多 200-400 的 IP 訪問量&#xff1a; 我又抽時間優…

深度學習之基于Pytorch框架手寫數字識別

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 手寫數字識別是數字圖像處理領域的一個經典問題&#xff0c;也是深度學習技術的一個常用應用場…

AWS計算之Amazon Lightsail

Amazon Lightsail是亞馬遜提供的一種簡化的虛擬私有服務器(VPS)服務&#xff0c;旨在幫助開發人員快速、輕松地搭建和管理虛擬服務器。Lightsail提供了預配置地計算資源、網絡、存儲和數據傳輸選項&#xff0c;用戶可以通過簡單的界面選擇所需的配置&#xff0c;輕松部署應用程…

51匯編--數碼管時鐘

實現一個24小時制的電子鐘程序&#xff0c;在實驗箱的6個數碼管上顯示時分秒&#xff08;用定時器0中斷更新計時時間&#xff0c;時間值以壓縮BCD碼形式保存在內部RAM的30H31H和32H單元&#xff09;。 PC機可通過串行口發送要設置的時間給單片機&#xff08;發送的時間格式為壓…

java 重寫接口的default方法

在Java 8中&#xff0c;接口可以包含默認方法&#xff08;default methods&#xff09;&#xff0c;這些方法可以有默認實現。如果一個類實現了包含默認方法的接口&#xff0c;并且沒有提供這個方法的實現&#xff0c;則會使用接口中的默認實現。 如果需要重寫接口中的默認方法…

【MySQL精通之路】SQL優化(1)-查詢優化(11)-多范圍查詢優化

主博客&#xff1a; 【MySQL精通之路】SQL優化(1)-查詢優化-CSDN博客 上一篇&#xff1a; 【MySQL精通之路】SQL優化(1)-查詢優化(10)-外部聯接簡化-CSDN博客 下一篇&#xff1a; 當基表很大且未存儲在存儲引擎的緩存中時&#xff0c;使用輔助索引上的范圍掃描讀取行可能會…

uniappx 獲取設備唯一標識(OAID、AAID、AndroidID、IMEI等) Ba-IdCode-U

簡介&#xff08;下載地址&#xff09; Ba-IdCode-U 是一款可以獲取國內各大手機廠商 OAID&#xff08;開放匿名設備標識&#xff09;及海外手機平臺 AAID&#xff08;安卓廣告標識&#xff09;的uniapp插件。另外也支持獲取 IMEI/MEID、AndroidID、WidevineID、PseudoID、GUI…

Spring Cloud Alibaba-06-Sleuth鏈路追蹤

Lison <dreamlison163.com>, v1.0.0, 2024.4.03 Spring Cloud Alibaba-06-Sleuth鏈路追蹤 文章目錄 Spring Cloud Alibaba-06-Sleuth鏈路追蹤為什么使用鏈路追蹤常見鏈路追蹤解決方案Sleuth概述概述Sleuth術語 Sleuth Zipkin 原理Sleuth原理簡述Zipkin 原理簡述 Sleut…

Python庫之`lxml`的高級用法深度解析

Python庫之lxml的高級用法深度解析 簡介 lxml是一個功能強大的第三方庫&#xff0c;它提供了對XML和HTML文檔的高效處理能力。除了基本的解析和創建功能外&#xff0c;lxml還包含了一些高級用法&#xff0c;這些用法可以幫助開發者在處理復雜文檔時更加得心應手。 高級解析技…

代碼隨想錄——路徑總和(Leetcode113)需要回顧

題目鏈接 遞歸 本題遞歸需要遍歷整棵樹&#xff0c;所以遞歸沒有返回值 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* T…

蘋果M4性能分析:進步神速?還有多少空間?

2024年初&#xff0c;蘋果推出了M4處理器&#xff0c;令人意外的是&#xff0c;它的發布距離M3發布僅僅過去了半年時間。更讓人驚訝的是&#xff0c;M4首次亮相于iPad Pro。這一新處理器不僅僅是M3的簡單升級版本&#xff0c;而是一次全面的架構優化。本文將詳細分析M4處理器的…

Vue基礎(1)數據綁定

一. 文本插值 普通文本可以使用雙大括號 {{ }} &#xff0c;要想插入 HTML&#xff0c;需要使用 v-html 指令。 <template><h1>Message: {{ state.msg }}</h1><p>{{ state.count 1 }}</p><p>{{ state.rawHtml }}</p><p v-html…