V少JS基礎班之第八彈:this

文章目錄

    • 一、 前言
    • 二、本節涉及知識點
    • 三、重點內容
      • 1、從新的角度認識this
      • 2、this是函數的參數
      • 3、this的值
      • 4、函數的調用
          • 1- 裸函數調用
          • 2- 函數作為構造函數調用
          • 3- 函數作為對象的方法調用
          • 4- 函數顯示調用
          • 5- 箭頭函數

一、 前言

第八彈內容是this。this相對來說難度不大,外面都說this背誦多過于理解,但是今天我們在這篇文章里由淺入深的理解一下this。文章更新有點慢,腦子一熱跑去學后端去了。最近趕趕進度,把之前丟的給補回來。
本系列為一周一更,計劃歷時6個月左右。從JS最基礎【變量與作用域】到【異步編程,密碼學與混淆】。希望自己能堅持下來, 也希望給準備入行JS逆向的朋友一些幫助, 我現在臉皮厚度還行。先要點贊,評論和收藏。也是希望如果本專欄真的對大家有幫助可以點個贊,有建議或者疑惑可以在下方隨時問。
先預告一下【V少JS基礎班】的全部內容,我做了一些調整。看著很少,其實,正兒八經細分下來其實挺多的,第一個月的東西也一點不少。
第一個月【變量作用域BOMDOM數據類型操作符
第二個月【函數閉包原型鏈this
第三個月【面向對象編程、 異步編程、nodejs】
第四個月【密碼學、各類加密函數】
第五個月【jsdom、vm2、express】
第六個月【基本請求庫、前端知識對接】

==========================================================

二、本節涉及知識點

函數的參數、對象、 this

==========================================================

三、重點內容

市面上很多資料都說:this的學習記憶多于理解。 只有記住了各種使用方法才能靈活運用。所以經常會有一批人上來就去背誦this的五種綁定方式:
默認綁定隱式綁定顯示綁定new綁定箭頭函數綁定
剛開始我也是這么學習的,但是說實話,這種靠背誦學習知識點的方式并不適合爬蟲逆向。

今天,我們還是以理解為主,讓我們開始今天的this學習。

1、從新的角度認識this

首先,學習這篇文章時,請丟掉在外面學習的關于this的任何知識。無論是python中的self,還是c++中的指針。

  • 在this的學習中,我們最先接觸的:
    • 第一個概念就是函數。
      • 函數是什么,不知道的去看我之前關于函數的章節。
    • 第二個要接觸的概念就是函數的參數
      • 一個函數可以傳參也可以不傳參
function say_hello(){console.log('hello world!')
}function sum_op(a, b) {return a + b;
}// 調用示例
say_hello()
console.log(sum_op(3, 5)); // 輸出 8

但是, 有一個參數, 無論函數傳不傳參,它都在那。我們不用賦值,只要函數調用時我們就可以使用的一個參數:this

那到這里,我們都能理解的話,那我們已經能掌握this了。 如果我們能理解函數的參數,那理解this就是很簡單的事。
我們丟掉我們無法理解的這句話:this是函數執行上下文里的隱藏變量
只需要記住這句話:

this是函數調用時的隱藏參數
1- this是什么:this是個參數
2- this的值: 對象 或 undefined
3- 什么時候用:函數調用時使用

我們今天的大部分內容都圍繞著這三個點展開

2、this是函數的參數

我們認識this的途徑不止從上下文中來,還可以從函數的參數的角度。
this是作為函數的隱藏參數在函數調用時傳遞。 函數在定義時我們給定一個形參,而只有在函數調用時,他才會有值。
甚至我們都不用去給他定義形參,在函數調用時,我們隨時可以使用this。hook住指定調用時的函數,隨意的就能取到this的值
在這里插入圖片描述

3、this的值

this的值只會有兩種類型: 對象 & undefined
在嚴格模式下,裸函數調用, this的返回值就是undefined。 在非嚴格模式下,裸函數調用返回的是window。 window本身就是一個對象。 那其他情況下也是如此,this要么是對象,要么是undefined。

4、函數的調用

說了這么多,其實就是一句話的事情。 那么我們學習this到底是在學習什么呢?那就是現在要說的。 函數的調用。 我們都說了:this是函數調用時的隱藏參數,參數的值只能是對象或者undefined。 那么什么情況下this是對象什么情況下是undefined。 我們如何判斷this的值呢。 這就是我們要學習的,函數的幾種調用方式。

函數的各種調用方式:

1- 裸函數調用

“裸函數調用”其實就是最直接、最普通的函數調用方式,沒有通過對象、call/apply/new 等手段修飾,只是單純調用函數本身。

function foo() {console.log(this);
}// 裸函數調用
foo();

為什么會有嚴格和非嚴格模式下值不同的區別。

其實很簡單,嚴格模式下,是真正的裸函數調用。 沒有任何對象調用它,函數自己執行了。此時,是沒有任何對象傳遞的,所以,此時的this是undefined。而在非嚴格模式下,瀏覽器環境中,所有的屬性和方法都是掛在在window上的,所以非嚴格模式下,瀏覽器中的裸函數調用不是真正的裸函數,而是window.fn()

同理,在不同的環境中裸函數調用的this值也是不一樣的。比如在瀏覽器中this為window,而在nodejs的全局中this的值則為global

這就是this背誦點之: 默認綁定
很多課件上來就說,this有五種綁定,我們背誦一下第一種綁定:默認綁定。默認綁定就是:當一個函數被調用時,如果 沒有明確指定 this(沒有作為對象方法調用、沒有 call/apply/bind、沒有 new 構造),那么 this 會按照 默認規則綁定。

我覺得這是一種本末倒置的學習方式,如果我們要理解默認綁定,因為由以下方式理解。

什么是默認綁定: 默認綁定就是裸函數調用,沒有任何第三方對象或者方法介入。直接用函數名+() 的形式運行函數,就是裸函數調用,也就是八股文中的 this的默認綁定

到此,我們就學會了this的第一個綁定方式。它是一種綁定方式,是由裸函數調用的方式決定了它的綁定方式。

2- 函數作為構造函數調用

那函數除了裸函數調用之外,還有哪些調用方式呢。

還記得函數篇中我們提到的構造函數嗎。 除了箭頭函數,任何普通函數都可以使用new的方式進行調用,此時的函數為構造函數。 當使用 new 調用一個函數時,就變成構造函數調用:

function Person(name) {this.name = name;
}const p = new Person('Alice');
console.log(p.name); // Alice
this 指向
構造函數調用時,this 永遠指向新創建的對象
和普通函數或方法調用不同:
  • 普通函數(裸函數調用)→ this 根據嚴格模式決定(undefined 或 window/global)
  • 方法調用 → this 指向點左邊對象
  • 構造函數 → this 永遠是新對象(或被返回對象覆蓋)

為什么呢, 我們看一下new調用函數時發生了什么

new 會做幾件事情:
創建一個空對象(obj)
將 this 指向這個新對象
執行構造函數的代碼
默認返回 this(新對象),除非顯式返回對象

所以此時的this指向是固定的。

3- 函數作為對象的方法調用

當函數作為 對象的屬性 被調用時,我們稱它為 方法調用。示例如下:

const obj = {x: 42,foo: function() {console.log(this);}
};obj.foo(); // 方法調用

this 指向: 調用時,點前面的對象

作為對象方法調用時的典型例子

1) 對象直接調用

const obj = {name: 'Alice',greet: function() {console.log(this.name);}
};obj.greet(); // Alice// 這里 this 指向 obj

2) 多層對象

const obj = {inner: {name: 'Bob',say: function() { console.log(this.name); }}
};obj.inner.say(); // Bob// 點運算符左邊是 obj.inner → this = obj.inner

3) 注意“丟失”情況

const obj = {x: 10,foo: function() { console.log(this.x); }
};const bar = obj.foo;
bar(); // undefined 或 window.x(非嚴格模式下) 
原因:bar 是函數的引用,不再是對象的方法調用. 這種情況就變成了 裸函數調用

總結:

在對象調用方法的情況下一定要注意對象丟失的情況。 使用函數賦值的時候,裸函數調用和對象的方法調用不能混為一談

好, 那對象.方法的形式,是什么綁定呢。 答案是: this的隱示綁定
當我們用對象.函數的方式調用函數,此時函數中的this就已經與該對象進行了綁定。 此時就是隱示綁定。

這就是我們背誦的this的第二個綁定方式

4- 函數顯示調用

不知道大家有沒有見過call和apply調用函數。比較經典的:

function sum(a, b, c) { return a + b + c; }
const nums = [1, 2, 3];
console.log(sum.apply(null, nums)); // 6
// 用于計算
const arr = [3, 1, 4];
const max = Math.max.apply(null, arr); // 4
// 查找最大值

其實,函數作為所謂的一等公民,他是給我們提供了很多的方便,有些已經寫好的庫,我們可以直接拿過來使用,我們對指定的對象用現有的函數,這種調用方式并不少見。

此時,我們對指定的函數進行call和apply與對象進行綁定。這種方式從this的角度看,他就是this的顯示綁定。我們直接明確的告訴大家,該函數是由該對象調用的。this也就是顯示的綁定在這個對象上。

總結:
ok,到這里大家已經學習了this的四種綁定方式了。 如此的水到渠成,完全不用背誦各種復雜的邏輯。函數怎么調用,this就是對應的綁定。 他的值也就是對應的值。

那我們最后再看一個特殊的綁定方式。

5- 箭頭函數

1) 箭頭函數的基本調用(裸函數調用)

const add = (a, b) => a + b;console.log(add(2, 3)); // 5

this 指向定義時的外層作用域(詞法綁定),而不是調用者

2)作為對象方法調用

const obj = {name: 'Alice',arrow: () => console.log(this.name)
};obj.arrow(); // undefined(this不是obj,而是定義時的外層 this)

箭頭函數不會綁定對象
無論怎么調用,this 都不會指向調用對象
如果想訪問對象屬性,需要用普通函數或外部變量

3) 作為回調函數調用

setTimeout(() => {console.log('Hello');
}, 1000);

常用于回調函數中
不會創建新的 this,繼承外層作用域的 this
避免了普通函數在回調中 this 指向全局或 undefined 的問題

4)與 call / apply / bind 的區別

const arrow = () => console.log(this);
arrow.call({ a: 1 }); // 依然指向定義時的 this

箭頭函數 不能被 call / apply 改變 this

總結:
調用方式:基本和普通函數一樣,可直接調用、作為回調或對象屬性
特殊點:
  • 沒有自己的 this,繼承外層作用域
  • 不能被顯式綁定(call/apply/bind 改變 this 無效)
  • 適合用于回調或內部函數,避免 this 指向混亂

口語化OS:

我們其實完全可以這么理解。當上下文在被調用的函數中時: 箭頭函數本身就無法改變this,所以,此時的this就是被調用函數當前狀態的this

這句話怎么理解呢。 就是,除了箭頭函數之外的其他調用方式大家都理解了。 此時情況:
在這里插入圖片描述
上下文正在debugger處。 在函數內部。 此時的this綁定的哪個就是哪個,這時候,函數內部有再多的箭頭函數,都不會改變this的指向。我們就記住一句話,箭頭函數無法改變this的綁定

以上就是this的五種綁定的全部內容。 今天就先到這里。如果本篇文章對大家有幫助,還望點贊關注,后續再給大家加一點this優先級的相關內容。

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

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

相關文章

《堆的詳解:結構、操作及堆排序算法》

目錄 一.堆的概念與結構 1.1 堆的概念 1.2 堆性質: 1.3 堆的結構定義 二.堆的初始化和銷毀 2.1 堆的初始化: 2.2 堆的銷毀: 三.堆的插入數據(含向上調整算法的實現) 3.1 插入邏輯 3.2 插入函數 3.3 向上調整算法 三. 堆的刪除數…

深入解析 Kubernetes 中的 Service 資源:為應用提供穩定的網絡訪問

什么是 Kubernetes 中的 Service? 在現代微服務架構中,服務之間的通信和負載均衡是至關重要的。尤其是在 Kubernetes 環境中,由于 Pod 是動態創建和銷毀的,如何為一組 Pod 提供穩定的訪問入口,成為了架構設計中的一個關…

使用Samba網絡磁盤作為MacOS時間機器的遠程備份磁盤

最近考慮MacOS系統升級,所以需要做磁盤備份,MacOS里有個備份磁盤很方便的工具:時間機器,可以自動定期備份磁盤,但是一般需要一個大點的移動硬盤插在macbook上選擇其為備份磁盤,可惜我并沒有移動硬盤&#x…

智能頭盔實時監控系統設計與實現

智能頭盔實時監控系統設計與實現 源碼 https://gitee.com/intostars/csdn-demo/tree/master/src/views/smartHelmet 預覽 一、功能概述 智能頭盔實時監控系統是基于Vue 3和TypeScript開發的一套用于遠程監控和控制智能頭盔設備的前端應用模塊。該系統通過WebSocket與后端服務…

Docker 學習筆記(八):容器運行時工具實踐及 OpenStack 部署基礎

容器管理工具Containerd nerdctl 實踐 nerdctl管理存儲 nerdctl命令創建容器的時候,可以使用-v選項將本地目錄掛載給容器實現數據持久化 示例: [rootlocalhost ~]# mkdir /data [rootlocalhost ~]# nerdctl run -d -v /data:/data busybox -- sleep infi…

Unity鍵盤控制角色運動

以下是一個完整的Unity角色移動和跳躍腳本,支持WASD或方向鍵移動: 使用說明 確保組件設置正確: 確保您的游戲對象有一個CharacterController組件 如果沒有,可以通過菜單 "Component -> Physics -> Character Controller" 添加 相機設置: 確保場景中有一…

linux 宏 DEVICE_ATTR

理解 DEVICE_ATTR DEVICE_ATTR 是 Linux 內核中用于創建設備屬性的宏&#xff0c;通常用于 sysfs 文件系統。通過 sysfs&#xff0c;用戶空間的程序可以讀取或修改內核中的設備屬性。DEVICE_ATTR 宏定義在 <linux/device.h> 頭文件中&#xff0c;用于聲明和定義一個設備屬…

MCP模型上下文協議以及交互流程

1. MCP 是什么全稱&#xff1a;Model Context Protocol定位&#xff1a;讓大語言模型&#xff08;LLM&#xff09;能在“上下文”之外&#xff0c;按統一格式訪問外部數據、調用插件、持久化狀態。動機&#xff1a;以前每家框架&#xff08;LangChain、LlamaIndex 等&#xff0…

MySQLTransactionRollbackException

問題描述mysql部署1主3從&#xff0c;昨天發現主庫有大量報警錯誤&#xff1a;Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ; Deadlock found when trying to get lock; …

Redis環境搭建指南:Windows/Linux/Docker多場景安裝與配置

Redis環境搭建指南&#xff1a;Windows/Linux/Docker多場景安裝與配置 1. Redis安裝方式概覽 1.1 安裝方式對比 安裝方式適用場景優點缺點難度Windows直接安裝開發調試安裝簡單&#xff0c;Windows兼容好性能不如Linux&#xff0c;生產不推薦?Linux源碼編譯生產環境性能最佳…

leetcode.80刪除有序數組中的重復項2

題目描述 給你一個有序數組 nums &#xff0c;請你 原地 刪除重復出現的元素&#xff0c;使得出現次數超過兩次的元素只出現兩次 &#xff0c;返回刪除后數組的新長度。 不要使用額外的數組空間&#xff0c;你必須在 原地 修改輸入數組 并在使用 O(1) 額外空間的條件下完成。…

運動卡新手入門及常見問題處理

1.新手入門1.1 插卡打開包裝&#xff0c;拿出PCI板卡&#xff0c;如下圖&#xff1a;打開電腦機箱蓋&#xff0c;找到PCI插槽&#xff0c;如下圖&#xff08;紅色框部分是PCI槽&#xff0c;有些主板上PCI槽是白色或其他顏色&#xff09;&#xff1a;插入板卡&#xff0c;如下圖…

PRINCE2與PMP項目管理體系對比

在全球范圍內&#xff0c;PRINCE2與PMP是兩大最具影響力的項目管理體系。PRINCE2注重流程和治理結構&#xff0c;強調“控制”與“規范”&#xff1b;而PMP基于PMBOK指南&#xff0c;強調知識體系和方法論的全面性&#xff0c;更關注“工具”與“實踐”。 不同體系的側重點&…

在UniApp跨平臺開發中實現相機自定義濾鏡的鏈式處理架構

以下是進階方案&#xff1a;架構核心設計分層結構$$Pipeline Capture \otimes Filter_1 \otimes Filter_2 \otimes \cdots \otimes Filter_n \otimes Render$$ 其中&#xff1a;$\otimes$ 表示鏈式處理操作符$Capture$ 為原始圖像采集層$Filter_n$ 為可插拔濾鏡單元$Render$ 為…

Mark5 穿越機電調深度解析:設計、選型、控制與實戰(下)

TIM_SetCompare3 (TIM1, T0 + T1 + T2); // W+? break;? case 3:? // U - 導通,V - 導通,W + 導通? TIM_SetCompare1 (TIM1, T0); // U-? TIM_SetCompare2 (TIM1, T0); // V-? TIM_SetCompare3 (TIM1, T0 + T1 + T2); // W+? break;? case 4:? // U - 導通…

背包問題從入門到入土

我在這里介紹4種常見的背包問題&#xff0c;這里我想按易 --> 難程度從01背包&#xff0c;完全背包&#xff0c;分組背包&#xff0c;多重背包的順序介紹。&#xff08;封面附在最后&#xff09;一&#xff0c;01背包問題&#xff08;后面三個背包問題的基礎&#xff09;01背…

Leetcode 18 java

?????1???????141. 環形鏈表1 題目 ?????1???????141. 環形鏈表 給你一個鏈表的頭節點 head &#xff0c;判斷鏈表中是否有環。 如果鏈表中有某個節點&#xff0c;可以通過連續跟蹤 next 指針再次到達&#xff0c;則鏈表中存在環。 為了表示給定鏈表…

Linux 正則表達式詳解(基礎 + 擴展 + 實操)

Linux 正則表達式詳解&#xff08;基礎 擴展 實操&#xff09; 正則表達式&#xff08;Regular Expression&#xff0c;簡稱 RE&#xff09;是 Linux 文本處理的核心工具&#xff0c;用于定義字符匹配模式&#xff0c;配合 grep、sed、awk 等工具可實現文本過濾、查找、替換等…

Json-rpc通信項目(基于C++ Jsoncpp muduo庫)

一、介紹RPC RPC&#xff08;Remote Procedure Call&#xff09;遠程過程調用&#xff0c;一種通過網絡從遠程計算器上請求服務&#xff0c;而不需要了解底層網絡通信細節&#xff0c;RPC可以使用多種網絡協議進行通信&#xff0c;并且在TCP/IP網絡四層模型中跨越了傳輸層和應…

RL【9】:Policy Gradient

系列文章目錄 Fundamental Tools RL【1】&#xff1a;Basic Concepts RL【2】&#xff1a;Bellman Equation RL【3】&#xff1a;Bellman Optimality Equation Algorithm RL【4】&#xff1a;Value Iteration and Policy Iteration RL【5】&#xff1a;Monte Carlo Learnin…