此關鍵字

關鍵字 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 方法,因此 myObject 是值 (this)就前文的情境來說,這似乎點出了技術性 範例不過,如要進一步使用 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 值。

使用 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 個繫結

如果使用類別做為建構函式, 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 (或嚴格模式中的 undefined):

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 物件