JavaScript中的this

在實際應用中,了解 this 的行為是非常重要的,特別是在編寫庫或框架時,或者當你需要在回調函數中訪問特定的上下文時,通常推薦使用箭頭函數或者其他方法來確保 this 的正確指向。

在ES6中,this 的值取決于它是如何被調用的。

this 不是一個函數或對象,而是一個特殊的關鍵字,其值在函數被調用時確定。

以下是在不同場景中 this 的值的概述:

01 全局作用域中的this

在JavaScript中,全局作用域指的是在代碼的任何位置都可以訪問的、變量和函數的范圍。

具體可以這么理解:當你在腳本的頂層(不在任何函數或代碼塊內部)聲明一個變量或函數時,它就在全局作用域中。

在全局作用域中,this 指向全局對象。

在瀏覽器環境中,全局對象是 window

在 Node.js 環境中,全局對象是 global

下面是一個在瀏覽器環境中演示這一點的簡單例子:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>"use strict"// 在全局作用域中console.log(this === window); // 應該輸出 true,表示 this 指向 window 對象console.log(this); // 輸出window對象// 定義一個全局變量var globalVar = "I am a global variable";// 使用 this 訪問全局變量console.log(this.globalVar); // 輸出 "I am a global variable"// 使用 window 訪問全局變量console.log(window.globalVar); // 輸出 "I am a global variable"// 定義一個函數,并在全局作用域中調用它function testFunction() {console.log(this); // 在瀏覽器環境中,輸出 window 對象,"use strict"下輸出undefined}testFunction();</script>
</body>
</html>

在這個例子中,this 在全局作用域中指向 window 對象。我們通過比較 thiswindow 來驗證這一點,并且使用 thiswindow 來訪問一個全局變量 globalVar,以證明它們都可以用來訪問全局作用域中的變量。

如果你在 Node.js 環境中運行代碼,全局對象將是 global,你可以類似地測試:

// 在 Node.js 的全局作用域中
console.log(this === global); // 應該輸出 true,表示 this 指向 global 對象// 定義一個全局變量
global.globalVar = "I am a global variable";// 使用 this 訪問全局變量
console.log(this.globalVar); // 輸出 "I am a global variable"// 使用 global 訪問全局變量
console.log(global.globalVar); // 輸出 "I am a global variable"// 定義一個函數,并在全局作用域中調用它
function testFunction() {console.log(this); // 在 Node.js 環境中,輸出 global 對象
}testFunction();

在這個 Node.js 例子中,this 在全局作用域中指向 global 對象,并且我們同樣使用 thisglobal 來訪問一個全局變量 globalVar

02 函數調用中的this

當一個函數不是作為對象的方法調用時(也就是說,它是獨立調用的,或者作為回調函數等被調用),this 的值在非嚴格模式下默認為全局對象(在瀏覽器中通常是 window),而在嚴格模式下它是 undefined

下面我將給出兩個示例程序來演示這個行為。

首先是非嚴格模式下的示例:

// 非嚴格模式
function exampleFunction() {console.log(this); // 在非嚴格模式下,this 指向 window 對象console.log(this.globalVar); // => I am a global variable
}exampleFunction();// 你可以通過檢查 window 對象來驗證這一點
function setGlobalVar() {window.globalVar = "I am a global variable";
}
setGlobalVar();
exampleFunction(); // 輸出包含 globalVar 的 window 對象

在這個例子中,exampleFunction 不是作為任何對象下的方法調用的,因此在非嚴格模式下,this 指向 window 對象。

我們在 setGlobalVar 函數中設置了一個全局變量 globalVar,然后在 exampleFunction 中通過 this 訪問它,證明了 this 確實指向 window

03 對象方法中的this

當一個函數作為對象的方法被調用時,this 關鍵字指向調用該方法的對象。下面是一個簡單的示例來展示這個行為:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>03-對象方法中的this</title>
</head>
<body><script>// 定義一個對象,它有一個方法叫做 greetconst person = {name: "Alice",getName: function () {console.log(this.name);}};// 調用 person 對象的 getName方法person.getName(); // 輸出 "Alice"// getName中this指向person對象,因為getName是作為 person 的方法被調用的</script>
</body>
</html>

在這個例子中,getName 函數是 person 對象的一個方法。當我們通過 person.getName() 調用這個方法時,this 關鍵字在函數內部指向了 person 對象。因此,this.name 訪問的是 person 對象的 name 屬性,并輸出了相應的信息。

04構造函數中的this

當一個函數被用作構造函數,并使用 new 關鍵字調用時,this 關鍵字會指向新創建的對象實例。下面是一個簡單的例子來說明這個行為:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>04-構造函數中的this</title>
</head>
<body><script>// 定義一個構造函數  function Person(name, age) {this.name = name;this.age = age;// 可以添加一個方法來訪問實例屬性  this.greet = function () {console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);};}// 使用 new 關鍵字來調用構造函數,創建一個新的對象實例  const alice = new Person('Alice', 25);alice.greet(); // 輸出 "Hello, my name is Alice and I'm 25 years old."  // 驗證 this 指向的是 alice 對象  console.log(alice.name); // 輸出 "Alice"  console.log(alice.age);  // 輸出 25  // 創建一個新的對象實例  const bob = new Person('Bob', 30);bob.greet(); // 輸出 "Hello, my name is Bob and I'm 30 years old."  // 驗證 this 指向的是 bob 對象  console.log(bob.name); // 輸出 "Bob"  console.log(bob.age);  // 輸出 30</script>
</body>
</html>

每次使用 new 關鍵字調用 Person 構造函數時,都會創建一個新的對象實例,并且 this 都會指向那個新對象。這就是為什么 alicebob 有各自獨立的 nameage 屬性,以及它們各自的 greet 方法。

在這個例子中,Person 函數被用作構造函數,因為我們使用 new 關鍵字來調用它。當構造函數被調用時,JavaScript 會創建一個新的空對象,并將這個新對象的內部鏈接([[Prototype]])設置為構造函數的 prototype 對象。然后,構造函數中的代碼執行,其中 this 關鍵字引用新創建的對象。

因此,當我們設置 this.namethis.age 時,我們實際上是在新創建的對象上設置屬性。同樣,this.greet 方法也是添加到新對象上的一個方法。

05箭頭函數中的this

箭頭函數在 JavaScript 中是一個非常重要的特性,它提供了一種更簡潔的函數書寫方式,并且它不綁定自己的 this,而是繼承自包圍它的函數或全局作用域的 this

這意味著在箭頭函數內部,this 的值是在定義箭頭函數時確定的,而不是在調用時確定的。

下面是一個簡單的示例來說明這個行為:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>05-箭頭函數中的this</title>
</head>
<body><script>function OuterFunction() {this.value = 42;// 這是一個普通函數  function innerFunction() {console.log(this.value); // 這里的 this 指向 OuterFunction 的實例  }// 這是一個箭頭函數  const arrowFunction = () => {console.log(this.value); // 這里的 this 繼承自 OuterFunction 的實例  };// 調用普通函數和箭頭函數  innerFunction(); // 輸出 42  arrowFunction(); // 輸出 42  }const obj = new OuterFunction();// 當我們在外部調用 innerFunction 時,this 指向全局對象(在瀏覽器中通常是 window)  // 因此,以下代碼會拋出一個錯誤,因為 this.value 是 undefined  obj.innerFunction(); // Uncaught TypeError: Cannot read property 'value' of undefined  // 但是,箭頭函數不會改變它的 this 上下文  // 因此,即使我們在外部調用 arrowFunction,它仍然可以訪問 OuterFunction 的 this 上下文  obj.arrowFunction(); // 輸出 42</script>
</body>
</html>

OuterFunction 中定義了一個普通函數 innerFunction 和一個箭頭函數 arrowFunction

OuterFunction 被調用時,它創建了一個新的對象實例,并且 thisinnerFunctionarrowFunction 中都指向這個新創建的對象。

當我們直接調用 obj.innerFunction() 時,this 指向了全局對象(在瀏覽器中是 window),因此 this.valueundefined,導致拋出一個錯誤。

然而,當我們調用 obj.arrowFunction() 時,即使我們是在外部調用的,arrowFunction 內部的 this 仍然指向 OuterFunction 的實例,因此可以正確地訪問 value 屬性。這是因為箭頭函數不綁定自己的 this,而是從定義它的上下文中繼承 this

TODO 嵌套函數

全局函數中的嵌套函數

對象方法中的嵌套函數

總結

場景this 的值描述
全局作用域window (瀏覽器) 或 global (Node.js)在全局作用域中,this 指向全局對象。
函數調用undefined (嚴格模式) 或 window (非嚴格模式)當一個函數不是作為對象的方法調用時,this 的值在非嚴格模式下是 window,在嚴格模式下是 undefined
對象方法調用該方法的對象當一個函數作為對象的方法被調用時,this 指向調用該方法的對象。
構造函數新創建的對象當一個函數作為構造函數使用 new 關鍵字調用時,this 指向新創建的對象。
箭頭函數定義時的上下文箭頭函數不綁定自己的 this,它繼承自包圍它的函數或全局作用域的 this
事件處理器調用事件處理器的對象在DOM事件處理器中,this 通常指向觸發事件的元素。
定時器函數undefined (嚴格模式) 或 window (非嚴格模式)setTimeoutsetInterval 的回調函數中,this 的值在非嚴格模式下是 window,在嚴格模式下是 undefined
Call, Apply, Bind指定的對象使用 callapplybind 方法可以顯式地設置 this 的值。

請注意,箭頭函數的行為略有不同,因為它們不綁定自己的 this。相反,它們從定義它們的上下文繼承 this

希望這個表格能幫助你理解ES6中 this 的不同行為!

在JavaScript中,特別是在ES6及其之后的版本中,回調函數中使用普通函數和箭頭函數時,this 的值可能會有所不同。這主要取決于回調函數的調用方式和上下文。以下是普通函數和箭頭函數在回調中作為方法使用時 this 的區別:

普通函數

當回調函數是一個普通函數時,this 的值通常取決于該函數如何被調用。如果該函數是作為對象的方法被調用,那么 this 將指向調用該方法的對象。如果該函數是作為回調函數被調用,并且沒有使用 callapplybind 方法來顯式地設置 this 的值,那么 this 可能會指向全局對象(在瀏覽器中是 window),或者在沒有嚴格模式的情況下是 undefined

例如:

function Example() {this.value = 5;setTimeout(function() {console.log(this.value); // this 指向全局對象或undefined(嚴格模式)}, 1000);
}const example = new Example(); // 輸出可能是 undefined,取決于環境

箭頭函數

箭頭函數不綁定自己的 this,它繼承自包圍它的函數或全局作用域的 this。這意味著在箭頭函數內部,this 的值將始終與包圍它的外部函數的 this 保持一致。

因此,當回調函數是箭頭函數時,this 將保持外部函數的 this 值,即使回調函數以不同的方式被調用。

例如:

function Example() {this.value = 5;setTimeout(() => {console.log(this.value); // this 繼承自Example函數的this,所以輸出5}, 1000);
}const example = new Example(); // 輸出 5

在這個例子中,即使 setTimeout 是一個全局函數,并且通常會導致回調函數中的 this 指向全局對象,但由于使用了箭頭函數,this 仍然保持了 Example 函數的上下文。

總結:在回調函數中,普通函數的 this 值可能會根據回調函數的調用方式而改變,而箭頭函數的 this 值則始終與其外部函數的 this 保持一致。因此,在需要確保 this 的值始終為特定上下文時,使用箭頭函數通常是更安全的選擇。

this不是常量, 它在程序中的不同地方會求值為不同的值。

this是面向對象編程中使用的關鍵字。在方法體中,this求值為調用方法的對象。

this標準函數箭頭函數 中有不同的行為。

1、標準函數中的 this

window.color = 'red';  
// 全局上下文中調用函數時,this 指向 windows
function sayColor() { console.log(this.color); 
} 
sayColor();    // 'red' let o = { color: 'blue' 
}; 
o.sayColor = sayColor; 
o.sayColor();  // 'blue' 

2、嵌套函數

嵌套函數普通函數內部的this是全局對象,嵌套箭頭函數的this是外層對象的this

注意:vue中相反:vue中嵌套普通函數內部的this是vue,而嵌套箭頭函數的this是全局對象

 let o = {m:function(){let self = this;this === o;console.log('o.m() this:',this);f();            function f(){this === o;self ===o;console.log('o.m.f() this:',this);}const f2 = ()=>{console.log('o.m.f2() this:',this);}f2();const f3 = (function(){console.log('o.m.f3() this:',this);}).bind(this);f3();}
}
o.m();
console.log(o);

2、箭頭函數中的this

window.color = 'red';  
let sayColor = () => console.log(this.color); 
sayColor();    // 'red' let o = { color: 'blue' 
}; 
o.sayColor = sayColor; 
o.sayColor();  // 'red' 

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

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

相關文章

web服務器nginx下載及在win11的安裝

一.背景 還是為了公司安排的師帶徒任務。 操作系統版本&#xff1a;win11 家庭版 mginx版本&#xff1a;1.24.0 二.nginx版本選擇與下載 我之前也寫過下載nginx下載_ngnix stable 下載-CSDN博客 不想看尋找過程的&#xff0c;直接點這里去下載https://nginx.org/download…

Docker 使用原理流程

# docker 是如何來的&#xff1f; a. linux 內核本身支持容器技術&#xff0c;LXC (市面上有很多基于 LXC 開發的容器管理軟件&#xff0c;如創建容器&#xff0c;查看容器&#xff0c;管理容器&#xff0c; docker 作為管理容器的一款代表工具軟件) b. 容器的作用&#xff0c;…

利用python批量將.shp文件轉換坐標生成.geojson文件,再將.geojson轉換成.csv文件,最后將csv文件插入數據庫表

第一步&#xff1a;.shp批量轉.geojson # author: JMY # 創建時間: 2024/2/26 17:12 # 批量將.shp文件生成geojson文件并轉換坐標為3857import os import geopandas as gpd# 定義輸入和輸出文件夾路徑 input_folder shp文件 output_folder geojson文件# 定義輸入和輸出坐標系…

【王道操作系統】ch1計算機系統概述-04操作系統結構

文章目錄 【王道操作系統】ch1計算機系統概述-04操作系統結構操作系統的內核操作系統的體系結構考綱新增內容&#xff08;紅色為全新內容&#xff0c;黃色為原有內容&#xff09;&#xff1a;01 分層結構02 模塊化03 宏內核&#xff08;大內核&#xff09;和微內核04 外核 【王…

redis03 八種數據類型

思維草圖 String類型 字符串類型&#xff0c;是redis中最簡單的存儲類型&#xff0c;可以包含任何數據&#xff0c;例如jpg圖片或者序列化的對象等&#xff0c;底層都是以字節數組形式存儲&#xff0c;最大能存儲512MB的數據。 常用命令 KEY命名規范 加前綴&#xff0c;分…

802.11局域網的 MAC 幀

目錄 802.11 局域網的 MAC 幀 802.11 數據幀的三大部分 1.關于 802.11 數據幀的地址 最常用的兩種情況 2.序號控制字段、持續期字段和幀控制字段 802.11 局域網的 MAC 幀 802.11 幀共有三種類型&#xff1a;控制幀、數據幀和管理幀。 802.11 數據幀的三大部分 MAC 首部&…

總結springboot啟動jar,指定配置文件

第一&#xff1a;覆蓋 -- 覆蓋系統中的文件中的application-dev.yml文件&#xff0c;兩種指定方法都可以 springboot默認優先讀取application.properties>application.yml>指定文件(application-dev.yml) 公共配置可以在application.yml&#xff0c;其他配置在applicatio…

基于 STM32U5 片內溫度傳感器正確測算溫度

目錄預覽 1、引言 2、問題 3、小結 01 引言 STM32 在內部都集成了一個溫度傳感器&#xff0c;STM32U5 也不例外。這個位于晶圓上的溫度傳感器雖然不太適合用來測量外部環境的溫度&#xff0c;但是用于監控晶圓上的溫度還是挺好的&#xff0c;以防止芯片過溫運行。 02 問題…

C# - 類與類之間的繼承關系判斷

Type.IsSubclassof(Type type) 作用&#xff1a;用來確定 一個類是否派生自另一個類/ValueType/Enum/委托 不能用于確定&#xff1a;接口是派生自另一個接口&#xff0c;還是類實現接口 class A{} class B : A{}A a; B b;var boo b.GetType().IsSubclassOf(typeof(A)) // t…

sqllabs第五關floor報錯注入

實驗環境sqllabs第五關 floor()報錯注入的原因是group by在向臨時表插入數據時&#xff0c;由于rand()多次計算導致插入臨時表時主鍵重復&#xff0c;從而報錯&#xff0c;又因為報錯前concat()中的SQL語句或函數被執行&#xff0c;所以該語句報錯且被拋出的主鍵是SQL語句或函…

go語言中的協程和Java中線程以及進程的區別

理解 Go 語言中的協程&#xff08;Goroutine&#xff09;、Java 中的線程和進程之間的區別可以從以下幾個方面來看&#xff1a; 輕量性&#xff1a; Goroutine&#xff08;協程&#xff09;&#xff1a; 協程是非常輕量級的執行單位&#xff0c;創建和銷毀的成本很低。在 Go 中…

深入理解Lambda表達式:基礎概念與實戰演練【第114篇—python:Lambda表達式】

深入理解Lambda表達式&#xff1a;基礎概念與實戰演練 在現代編程語言中&#xff0c;Lambda表達式作為一種輕量級的匿名函數形式&#xff0c;越來越受到程序員的青睞。特別是在函數式編程興起的今天&#xff0c;Lambda表達式在簡化代碼、提高可讀性方面發揮著重要作用。本文將…

C++筆記(六)--- 靜態成員變量/函數(static)

目錄 C語言中靜態變量 C靜態成員變量 C靜態成員函數 C語言中靜態變量 1.函數內部用static修飾的變量&#xff0c;只能在此函數使用&#xff0c;但所修飾的變量不隨函數釋放而釋放&#xff0c;下次調用時的值仍為上次結束時的值2.static修飾的全局變量只能在其定義的文件使用…

華為OD技術面試案例6-2024年

個人情況&#xff1a;西電本&#xff0c;二戰某985基本寄了。知識儲備方面&#xff1a;無任何408基礎&#xff0c;學校開過數據結構課程60分過&#xff0c;python純靠自學&#xff0c;無任何刷題經驗&#xff0c;無項目經驗&#xff0c;簡歷東拼西湊。 大概是12月底和OD聯系&a…

數據可視化原理-騰訊-熱力圖

在做數據分析類的產品功能設計時&#xff0c;經常用到可視化方式&#xff0c;挖掘數據價值&#xff0c;表達數據的內在規律與特征展示給客戶。 可是作為一個產品經理&#xff0c;&#xff08;1&#xff09;如果不能夠掌握各類可視化圖形的含義&#xff0c;就不知道哪類數據該用…

CSP-201712-2-游戲

CSP-201712-2-游戲 解題思路 初始化變量&#xff1a;定義整數變量n和k&#xff0c;分別用來存儲小朋友的總數和淘汰的特定數字。然后定義了num&#xff08;用來記錄當前報的數&#xff09;和peopleIndex&#xff08;用來記錄當前報數的小朋友的索引&#xff09;。 初始化小朋…

MATLAB環境下基于離散小波變換的體外血管圖像處理

下面簡要介紹小波變換的部分應用。 信號去噪。小波去噪是根據有效信號和噪聲信號在小波變換后表現出的不同特性實現的&#xff0c;一般可用于去除語音、圖像、視頻等中的噪聲信號。小波去噪方法根據對小波系數的非線性處理方式分為三類&#xff0c;分別是小波變換模極大值去噪…

電子電器架構新趨勢 —— 最佳著力點:域控制器

電子電器架構新趨勢 —— 最佳著力點&#xff1a;域控制器 我是穿拖鞋的漢子&#xff0c;魔都中堅持長期主義的汽車電子工程師&#xff08;Wechat&#xff1a;gongkenan2013&#xff09;。 老規矩&#xff0c;分享一段喜歡的文字&#xff0c;避免自己成為高知識低文化的工程師…

備戰藍橋杯---狀態壓縮DP基礎1之棋盤問題

它只是一種手段&#xff0c;一種直觀而高效地表示復雜狀態的手段。 我們先來看一道比較基礎的&#xff1a; 直接DFS是肯定不行&#xff0c;我們發現對某一行&#xff0c;只要它前面放的位置都一樣&#xff0c;那么后面的結果也一樣。 因此我們考慮用DP&#xff0c;并且只有0/…

Vue3+Element-Plus中ELMessage樣式丟失處理

Vu3Element-Plus項目中,element-plus使用按需引入有時會出現樣式失效和在vscode中使用會報錯[找不到名稱“ElMessage”。ts(2304)]錯誤 ELMessage彈框樣式丟失處理方法 使用按需引入就不能手動再引入 import { ElMessage } from "element-plus";ElMessage.success…