〖大前端 - 基礎入門三大核心之JS篇(51)〗- 面向對象之認識上下文與上下文規則

  • 說明:該文屬于 大前端全棧架構白寶書專欄,目前階段免費如需要項目實戰或者是體系化資源,文末名片加V!
  • 作者:哈哥撩編程,十余年工作經驗, 從事過全棧研發、產品經理等工作,目前在公司擔任研發部門CTO。
  • 榮譽:2022年度博客之星Top4、2023年度超級個體得主、谷歌與亞馬遜開發者大會特約speaker全棧領域優質創作者

  • 🏆 白寶書系列
    • 🏅 啟示錄 - 攻城獅的自我修養
    • 🏅 Python全棧白寶書
    • 🏅 ChatGPT實踐指南白寶書
    • 🏅 產品思維訓練白寶書
    • 🏅 全域運營實戰白寶書
    • 🏅 大前端全棧架構白寶書


文章目錄

  • ?認識上下文
  • ?上下文規則
    • 🌟上下文規則1
    • 🌟上下文規則2
    • 🌟上下文規則3
    • 🌟上下文規則4
    • 🌟上下文規則5
    • 🌟上下文規則6

?認識上下文

小時候學習做閱讀理解時,老師經常會強調,注意上下文。比如有一個句子:這是一個好習慣,我們應該堅持。如果不結合上文的意思,根本不知道“這”指的是什么。如果結合上文,比如,隨手關燈,這是一個好習慣,我們應該堅持。我們就知道此時的“這”指的是“隨手關燈”,那么整個句子的語義就好理解了。

在函數中,也經常需要結合上下文來編寫和理解代碼。

函數中可以使用this,表示函數的上下文

與中文中的“這”類似,函數中的this具體指代什么必須通過調用函數時的“前言后語”來判斷

下面看一個例子:

  • 第一種調用方式:對象打點調用自己的方法:
var xiaomumu = {name: '小沐沐',age: 2,sex: '男',hobbies: ['秋千', '滑梯'],sayHello: function () {console.log('Hello, 我是' + this.name + ',我今年' + this.age + '歲了');}
};
xiaomumu.sayHello();   // Hello, 我是小沐沐,我今年2歲了
  • 第二種調用方式:對象的方法被賦值給一個全局變量,全局變量加圓括號調用:
var xiaomumu = {name: '小沐沐',age: 2,sex: '男',hobbies: ['秋千', '滑梯'],sayHello: function () {console.log('Hello, 我是' + this.name + '我今年' + this.age + '歲了');}
};var sayHello = xiaomumu.sayHello;   // 將這個屬性存入了一個全局變量(變量的名稱可以和屬性名相同,方便理解)
sayHello();   //Hello, 我是undefined我今年undefined歲了

這兩種調用方式,this指代的對象分別是:

  • 第一種,對象打點調用方式,函數中的this指代這個打點的對象
  • 第二種,圓括號直接調用函數,函數中的this指代window對象

其實可以這么理解,第二種中,因為全局變量都是window的屬性,相當于用window.sayHello()的方式調用了這個函數。所以this指代的就是window對象。

所以我們一定要記住:只有函數被調用時,我們才能知道this指代的是什么函數的上下文由函數的調用方式決定,同一個函數,用不同的形式調用它,則函數的上下文不同

?上下文規則

我們知道,不同的調用方式,函數的上下文就不同,那么我們怎么去判斷函數的上下文呢?這就要學習各種不同的函數調用規則。

🌟上下文規則1

規則1:對象打點調用它的方法函數,則函數的上下文是這個打點的對象

下面看幾個案例,練習一下:

題目一: 下面代碼的運行結果是什么?

function fn() {console.log(this.a + this.b);
}
var obj = {a: 11,b: 22,fn: fn
};obj.fn();

運行結果:33

題目二: 下面代碼的運行結果是什么?

var obj1 = {a: 1,b: 2,fn: function () {console.log(this.a + this.b);}
};var obj2 = {a: 3,b: 4,fn: obj1.fn
};obj2.fn();

運行結果: 7

一定要記住,誰打點調用函數,函數中的this指代的就是誰

題目三: 下面代碼的運行結果是什么?

function outer() {var a = 11;var b = 22;return {a: 33,b: 44,fn: function () {console.log(this.a + this.b);}};
}outer().fn();

運行結果:77

上面的代碼中,outer()返回了一個對象,相當于還是一個對象打點調用了函數,所以適用于對象打點調用函數,函數的上下文就是這個對象的規則。

題目四: 下面代碼的運行結果是什么?

function fun() {console.log(this.a + this.b);
}var obj = {a: 1,b: 2,c: [{a: 3,b: 4,c: fun}]
};var a = 5;
obj.c[0].c();

運行結果:7

上面的代碼中,最終調用函數的是obj.c[0]這個對象,所以函數中的this指代的就是obj.c[0]

🌟上下文規則2

規則2:圓括號直接調用函數,則函數的上下文是window對象

題目一: 下面代碼的運行結果是什么?

var obj1 = {a: 1,b: 2,fn: function () {console.log(this.a + this.b);}
};
var a = 3;
var b = 4;var fn = obj1.fn;
fn();

運行結果:7

題目二: 下面代碼的運行結果是什么?

function fun() {return this.a + this.b;
}
var a = 1;
var b = 2;
var obj = {a: 3,b: fun(),fun: fun
};
var result = obj.fun();
console.log(result);

運行結果:6,題目分析如下:

image-20230509165256380

這是一道非常正規的面試題,大家一定要學會分析其中的代碼邏輯

🌟上下文規則3

規則3:數組(類數組對象)枚舉出函數進行調用,上下文是這個數組(類數組對象)

數組[下標]()

類數組對象:所有鍵名為自然數序列(從0開始),且有length屬性的對象

arguments對象是最常見的類數組對象,它是函數的實參列表

題目一: 下面代碼的運行結果是什么?

var arr = ['A', 'B', 'C', function () {console.log(this[0]);
}];arr[3]();

運行結果: “A”

上面的代碼適用規則3,this指代的就是arr這個數組

題目二: 下面代碼的運行結果是什么?

function fun() {arguments[3]();
}fun('A', 'B', 'C', function () {console.log(this[1]);
});

運行結果:“B”。我們可以打印一下arguments,可以看到arguments是一個類數組對象,里面其實就是fun()函數被調用時,傳入的實參:

image-20230509164048474

🌟上下文規則4

規則4:IIFE中的函數,上下文是window對象。(IIFE在以前的文中提到過,是立即可執行函數。)

(function (){

? //立即可執行函數

})()

題目一: 下面代碼的運行結果是什么?

var a = 1;
var obj = {a: 2,fun: (function () {var a = this.a;return function () {console.log(a + this.a);}})()
};
obj.fun();

運行結果:3。這是一個大廠的面試題,題目分析如下:

image-20230509165927143

🌟上下文規則5

規則5:定時器、延時器調用函數,上下文是window對象

setInterval(函數,時間);

setTimeout(函數,時間);

題目一: 下面代碼的運行結果是什么?

var obj = {a: 1,b: 2,fun: function () {console.log(this.a + this.b);}
};
var a = 3;
var b = 4;setTimeout(obj.fun, 2000);

運行結果:7。因為用延時器調用的函數,適用規則5,this指代的就是window對象,即this.athis.b的值分別是3,4

題目二: 下面代碼的運行結果是什么?

var obj = {a: 1,b: 2,fun: function () {console.log(this.a + this.b);}
};
var a = 3;
var b = 4;setTimeout(function () {obj.fun();    //適用規則1
}, 2000);

運行結果:3。這里要注意,延時器不是直接調用obj里的fun函數,而是一個匿名函數,這個匿名函數里又調用了obj.fun(),所以此時的this應指代的是obj這個對象,即this.athis.b的值分別是1,2

🌟上下文規則6

規則6:事件處理函數的上下文是綁定事件的DOM元素

DOM元素.onclick = function() {

};

題目一: 點擊哪個盒子,哪個盒子就變紅,要求使用同一個事件處理函數實現(不能用事件委托)

<html lang="en">
<head><style>div {width: 200px;height: 200px;float: left;border: 1px solid #000;margin-right: 10px;}</style>
</head>
<body><div id="box1"></div><div id="box2"></div><div id="box3"></div><script>function setColorToRed(o) {this.style.backgroundColor = 'red';}var box1 = document.getElementById('box1');var box2 = document.getElementById('box2');var box3 = document.getElementById('box3');box1.onclick = function () {setColorToRed(box1);}box1.onclick = setColorToRed;box2.onclick = setColorToRed;box3.onclick = setColorToRed;</script>
</body>
</html>

運行結果:點擊哪個盒子,哪個盒子就變紅。這里的this指代的就是綁定事件的DOM元素;注意區分this和e.target的不同

題目二: 點擊哪個盒子,哪個盒子在2000毫秒后就變紅,要求使用同一個事件處理函數實現(不能用事件委托)

題目分析:這個題目其實就是上個題目+一個延時器,但是需要注意的是加上延時器后,this指代的可能會不一樣,所以需要使用一個程序猿非常常用的技術:備份上下文

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div {width: 200px;height: 200px;float: left;border: 1px solid #000;margin-right: 10px;}</style>
</head>
<body><div id="box1"></div><div id="box2"></div><div id="box3"></div><script>function setColorToRed(o) {//備份上下文var self = this;  // 通常使用self來備份上下文,也有使用that或_this的,這個技術非常的常用!setTimeout(() => {self.style.backgroundColor = 'red';}, 2000);}var box1 = document.getElementById('box1');var box2 = document.getElementById('box2');var box3 = document.getElementById('box3');box1.onclick = function () {setColorToRed(box1);}box1.onclick = setColorToRed;box2.onclick = setColorToRed;box3.onclick = setColorToRed;</script>
</body>
</html>

注意:程序員在書寫this的時候通常會看一下這個this到底指代什么,需不需要備份

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

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

相關文章

qt-C++筆記之addAction和addMenu的區別以及QAction的使用場景

qt-C筆記之addAction和addMenu的區別以及QAction的使用場景 code review! 文章目錄 qt-C筆記之addAction和addMenu的區別以及QAction的使用場景1.QMenu和QMenuBar的關系與區別2.addMenu和addAction的使用場景區別3.將QAction的信號連接到槽函數4.QAction的使用場景5.將例1修改…

基于單片機智能澆花控制系統設計

**單片機設計介紹&#xff0c;基于單片機智能澆花控制系統設計 文章目錄 一 概要二、功能設計設計思路 三、 軟件設計原理圖 五、 程序六、 文章目錄 一 概要 基于單片機的智能澆花控制系統可以通過水泵、傳感器和單片機等硬件組件實現自動澆水&#xff0c;減輕人工澆花的工作…

【LeeCode】151.翻轉字符串里的單詞

給你一個字符串 s &#xff0c;請你反轉字符串中 單詞 的順序。 單詞 是由非空格字符組成的字符串。s 中使用至少一個空格將字符串中的 單詞 分隔開。 返回 單詞 順序顛倒且 單詞 之間用單個空格連接的結果字符串。 注意&#xff1a;輸入字符串 s中可能會存在前導空格、尾隨…

Mysql mybatis 語法示例

service package com.ruoyi.goods.service;import java.util.List; import com.ruoyi.goods.domain.GoodsProducts;/*** 商品Service接口* * author ruoyi* date 2023-08-27*/ public interface IGoodsProductsService {/*** 查詢商品* * param ProductID 商品主鍵* return 商…

基于OpenCV+CNN+IOT+微信小程序智能果實采摘指導系統——深度學習算法應用(含python、JS工程源碼)+數據集+模型(三)

目錄 前言總體設計系統整體結構圖系統流程圖 運行環境Python環境TensorFlow 環境Jupyter Notebook環境Pycharm 環境微信開發者工具OneNET云平臺 模塊實現1. 數據預處理1&#xff09;爬取功能2&#xff09;下載功能 2. 創建模型并編譯1&#xff09;定義模型結構2&#xff09;優化…

Docker與K8s的區別

Docker 和 K8s&#xff08;Kubernetes&#xff09;是兩個不同的技術&#xff0c;它們在容器化應用程序的管理和部署方面有著不同的角色和功能。 Docker 是一種容器化平臺&#xff0c;它允許您將應用程序及其所有依賴項打包到一個獨立的、可移植的容器中。Docker 提供了一種輕量…

《PySpark大數據分析實戰》-03.了解Hive

&#x1f4cb; 博主簡介 &#x1f496; 作者簡介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 熱衷于各種主流技術&#xff0c;熱愛數據科學、機器學習、云計算、人工智能。 通過了TiDB數據庫專員&#xff08;PCTA&#xff09;、TiDB數據庫專家&#xff08;PCTP…

恢復Django 項目

隨筆記錄 目錄 1. 重建Mysql DB 2. 啟動Django 項目 2.1 確保你的系統上已安裝pip工具。你可以使用以下命令來檢查pip是否已安裝 2.2 安裝Packages 2.2.1 安裝Django 2.2.2 安裝pymysql 2.2.3 安裝 kafka 2.2.4 安裝 requests 2.2.5 安裝simplepro 2.2.6 安裝libjp…

持續集成交付CICD:GitLabCI上傳Nexus制品

目錄 一、實驗 1.GitLabCI上傳Nexus制品 2.優化GitLabCI&#xff08;引用系統變量&#xff09; 3.添加if條件判斷項目類型 4.優化GitLabCI&#xff08;模板類&#xff09; 二、問題 1.GitLabCI獲取jar文件失敗 2. GitLabCI獲取流水線項目命名空間失敗 3.GItLab Packag…

.NET 8 編寫 LiteDB vs SQLite 數據庫 CRUD 接口性能測試(準備篇)

WebAppDbTest 項目準備 項目準備1、.net cli 創建項目2、nuget 包引用和項目結構2.1、項目添加相關 nuget 包2.2、WebAppDbTest 項目結構 3、項目代碼說明3.1、CSharp/C# 類文件說明3.2、json 配置文件說明 4、項目運行預覽 數據庫 .db 文件準備1、創建 SQLite 數據庫1.1、在 W…

c#讀取CSV文件跟Excel導入成DataTble

1.讀取CSV文件 /// <summary>/// 讀取CSV文件/// </summary>/// <param name"fileName">文件路徑</param>public static DataTable ReadCSV(string fileName){DataTable dt new DataTable();FileStream fs new FileStream(fileName, FileM…

Python---綜合案例

一、系統需求分析 1、需求分析 使用面向對象編程思想完成學員管理系統的開發&#xff0c;具體如下&#xff1a; ① 系統要求&#xff1a;學員數據存儲在文件中 ② 系統功能&#xff1a;添加學員、刪除學員、修改學員信息、查詢學員信息、顯示所有學員信息、保存學員信息及退…

56.windows docker 安裝ES、Go操作ES

文章目錄 一、環境準備1、 docker安裝ES2、啟動容器3、圖像化客戶端工具ElasticSearch-Head 二、Go ES連接與認證1、 連接ES2、配置ES認證 三、索引的增刪改查四、文檔的增刪改創建單個文檔根據文檔id刪除文檔批量刪除文檔批量創建文檔 五、文檔查詢列表查詢精確匹配模糊匹配嵌…

ubuntu18.04配置cuda+cudnn+tensorrt+anconda+pytorch-gpu+pycharm

一、顯卡驅動安裝 執行nvidia-smi查看安裝情況 二、cuda安裝 cuda官網下載cuda_11.6.2_510.47.03_linux.run&#xff0c;安裝執行 sudo sh cuda_11.6.2_510.47.03_linux.run提升安裝項&#xff0c;驅動不用安裝&#xff0c;即第一項&#xff08;Driver&#xff09;&#xff…

如何使用Java在Excel中添加動態數組公式?

本文由葡萄城技術團隊發布。轉載請注明出處&#xff1a;葡萄城官網&#xff0c;葡萄城為開發者提供專業的開發工具、解決方案和服務&#xff0c;賦能開發者。 前言 動態數組公式是 Excel 引入的一項重要功能&#xff0c;它將 Excel 分為兩種風格&#xff1a;Excel 365 和傳統 …

虹科技術 | IO-Link Wireless如何賦能工廠車間邁向無線自動化?

大規模定制、卓越運營和商業智能正在從根本上改變制造業&#xff0c;為了在競爭中立于不敗之地&#xff0c;制造商需要更加靈活、通用、可擴展和具有成本效益的機器和生產線。隨著制造商向工業 4.0 邁進&#xff0c;更好的適應性、更高的吞吐量和更短的停機時間是他們的共同要求…

打包CSS

接上一個打包HTML繼續進行CSS的打包 1.在之前的文件夾里的src文件夾創建一個css文件 2.在瀏覽器打開webpack——>中文文檔——>指南——>管理資源——>加載CSS 3.復制第一句代碼到終端 4.復制下圖代碼到webpack.config.js腳本的plugins&#xff1a;[.....]內容下…

【docker】Hello World

搜索hello-world鏡像 docker search hello-world拉去鏡像 docker pull hello-world查看本地鏡像 docker images 運行鏡像 docker run hello-world查看所有的容器 docker ps -a查詢start狀態容器 docker ps 輸出介紹 CONTAINER ID: 容器 ID。IMAGE: 使用的鏡像。COMMAN…

面試經典150題(14)

leetcode 150道題 計劃花兩個月時候刷完&#xff0c;今天&#xff08;第五天&#xff09;完成了1道(14)150&#xff1a; 14. &#xff08;134. 加油站&#xff09;題目描述&#xff1a; 在一條環路上有 n 個加油站&#xff0c;其中第 i 個加油站有汽油 gas[i] 升。 你有一輛油…