此關鍵字

關鍵字 this 是指在呼叫時繫結至函式的物件值,也就是說,其值會因函式是否以方法、獨立函式或建構函式的形式呼叫而有所不同。

呼叫函式時,系統會在背景建立關鍵字 this 的例項,做為包含該函式的物件參照,讓您可以存取在其範圍內定義的屬性和方法。使用 this 的方式與使用 const 宣告的變數類似。就像常數一樣,this 無法移除,且無法重新指派其值,但 this 關鍵字所包含物件的各項方法和屬性可以變更。

全域繫結

在函式或物件內容之外,this 會參照 globalThis 屬性,這是大多數 JavaScript 環境中全域物件的參照。在網路瀏覽器中執行的指令碼情境中,全域物件是 window 物件:

this; > Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...} 

在 Node.js 中,globalThisglobal 物件:

$ node Welcome to Node.js v20.10.0. Type ".help" for more information. > this <ref *1> Object [global] { ... } 

在嚴格模式之外,this 也會參照獨立函式中的全域物件,因為父項 Window 是實際「擁有」這些函式的物件。

function myFunction() {     console.log( this ); } myFunction(); > Window {...}  (function() {     console.log( this ); }()); > Window {...} 

使用嚴格模式時,this 在獨立函式內的值為 undefined

(function() {     "use strict";     console.log( this ); }()); > undefined 

在嚴格模式推出前,thisnullundefined 值會由對全域物件的參照取代。有時您可能會看到全域繫結被稱為「預設繫結」,這是因為這種舊版行為。

隱含繫結

當函式以物件方法的形式呼叫時,該方法內的 this 例項會參照包含該方法的物件,並提供對該方法和屬性的存取權:

let myObject = {     myValue: "This is my string.",     myMethod() {             console.log( this.myValue );     } };  myObject.myMethod(); > "This is my string." 

this 的值似乎取決於函式及其包函物件的定義方式。相反地,this 值的內容為目前的執行內容。在本例中,執行階段是 myObject 物件呼叫 myMethod 方法,因此 myObjectthis 的值。在先前的範例中,這可能看起來像是技術性問題,但對於 this 的進階用法來說,這是必須留意的關鍵差異。

一般來說,請以不預期周圍程式碼具有任何特定結構的方式使用 this。這項規則的例外狀況是 ES5 箭頭函式

箭頭函式中的 this

箭頭函式中,this 會解析為語意上包函環境中的繫結。也就是說,箭頭函式中的 this 會參照該函式最接近的包函式中的 this 值:

let myObject = {     myMethod() { console.log( this ); },     myArrowFunction: () => console.log( this ),     myEnclosingMethod: function () {         this.myArrowFunction = () => { console.log(this) };     } };  myObject.myMethod(); > Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }  myObject.myArrowFunction(); > Window {...} 

在上一個範例中,myObject.myMethod() 會將 myObject 記錄為「擁有」該方法的物件,但 myObject.myArrowFunction() 會傳回 globalThis (或 undefined),因為箭頭函式中的 this 例項會改為參照最高的包函範圍。

在以下範例中,myEnclosingMethod 會在執行時,在包含它的物件上建立箭頭函式。箭頭函式中的 this 例項現在會參照包函環境中的 this 值,也就是包含該箭頭函式的做法。由於 myEnclosingMethod 內的 this 值參照 myObject,因此在定義箭頭函式後,箭頭函式內的 this 也會參照 myObject

let myObject = {     myMethod() { console.log( this ); },     myEnclosingMethod: function () {         this.myArrowFunction = () => { console.log(this) };     } };  myObject.myEnclosingMethod(); myObject.myArrowFunction(); > Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() } 

明確繫結

隱含繫結可處理大多數使用 this 的用途。不過,您有時可能需要 this 的值來代表特定執行作業環境,而非假設的作業環境。以下是說明這項功能的示例 (雖然稍微過時),這個示例會在 setTimeout 的回呼函式中使用 this,因為這個回呼具有獨特的執行情境:

var myObject = {   myString: "This is my string.",   myMethod() {     console.log( this.myString );   } }; myObject.myMethod(); > "This is my string."  setTimeout( myObject.myMethod, 100 ); > undefined 

雖然 setTimeout 的這個特定缺點已由其他功能解決,但先前已透過在預期情境範圍內明確參照 this 的值,解決了類似的「遺失」this的問題。您可能偶爾會在舊版程式碼集區中,看到 this 例項以 thatself_this 等 ID 指派給變數。以下是含有傳遞 this 值的變數常見的 ID 慣例。

使用 call()bind()apply() 方法呼叫函式時,this 會明確參照要呼叫的物件:

let myFunction = function() {     console.log( this.myValue ); }  let myObject = {    "myValue" : "This is my string."  };  myFunction.call( myObject ); > "This is my string." 
var myObject = {   myString: "This is my string.",   myMethod() {     console.log( this.myString );   } };  setTimeout( myObject.myMethod.bind( myObject ), 100 ); > "This is my string." 

明確繫結會覆寫隱含繫結提供的 this 值。

let myObject = {     "myValue" : "This string sits alongside myMethod.",     myMethod() {         console.log( this.myValue );     } }; let myOtherObject = {     "myValue" : "This is a string in another object entirely.", };  myObject.myMethod.call( myOtherObject ); > "This is a string in another object entirely." 

如果以會將 this 值設為 undefinednull 的方式呼叫函式,該值會在嚴格模式外部由 globalThis 取代:

let myFunction = function() {     console.log( this ); }  myFunction.call( null ); > Window {...} 

同樣地,如果以會為 this 提供基本值的方式呼叫函式,該值會在嚴格模式外替換為基本值的包裝函式物件

let myFunction = function() {     console.log( this ); }  let myNumber = 10;  myFunction.call( myNumber ); > Number { 10 } 

在嚴格模式中,傳遞的 this 值不會以任何方式強制轉換為物件,即使是基本、nullundefined 值也是如此:

"use strict"; let myFunction = function() {     console.log( this ); }  let myNumber = 10;  myFunction.call( myNumber ); > 10  myFunction.call( null ); > null 

new 繫結

class 用於使用 new 關鍵字的建構函式時,this 會參照新建立的例項:

class MyClass {     myString;     constructor() {         this.myString = "My string.";     }     logThis() {         console.log( this );     } } const thisClass = new MyClass();  thisClass.logThis(); > Object { myString: "My string." } 

同樣地,使用 new 呼叫的建構函式內的 this 值會參照要建立的物件:

function MyFunction() {   this.myString = "My string.";   this.logThis = function() {     console.log( this );   } } const myObject = new MyFunction();  myObject.logThis(); > Object { myString: "My string.", logThis: logThis() } 

事件處理常式繫結

在事件處理常式的內容中,this 的值會參照叫用該事件的物件。在事件處理常式的回呼函式中,this 會參照與處理常式相關聯的元素:

let button = document.querySelector( "button" );  button.addEventListener( "click", function( event ) { console.log( this ); } ); 

當使用者與上一個程式碼片段中的 button 互動時,結果會是包含 <button> 本身的元素物件:

> Button {} 

當箭頭函式用於事件監聽器回呼時,this 的值會再次由最接近的包函執行作業內容提供。在頂層,這表示事件處理常式回呼函式中的 thisglobalThis

let button = document.querySelector( "button" );  button.addEventListener( "click", ( event ) => { console.log( this ); } ); > undefined 

如同其他物件一樣,當您使用 call()bind()apply() 方法參照事件監聽器的回呼函式時,this 會明確參照物件:

let button = document.querySelector( "button" ); let myObject = {     "myValue" : true }; function handleClick() {     console.log( this ); }  button.addEventListener( "click", handleClick.bind( myObject ) ); > Object { myValue: true } 

進行隨堂測驗

如果是在網路瀏覽器中執行的指令碼,在函式或物件內容之外使用 this 時,系統會參照哪個全域物件?

window 物件
browser 物件
undefined 物件