解釋 JavaScript 中 this 的值?
2022年10月9日
大部分 JavaScript 學習者在學習 this
概念時通常覺得一頭霧水,許多人覺得是 JavaScript 中最複雜的概念之一,然而 this
值是 JavaScript 面試經典題,搞懂 this 值也是戰勝面試的第一步。本篇文章會整理出來 this
值的 5 種判斷方式,讓讀者在面試時能輕易掌握這些概念。
在 JavaScript 中,this
的值是動態的,通常會由被呼叫的函式來決定。所以,影響 this
的值不是宣告的時機,關鍵在於在哪裡被調用。
this 值 5 種判斷方式
1. 函式調用
當一個函式不是屬於一個物件中的方法時,直接作為函式來調用時,this
會指向全局物件,在瀏覽器中,默認為 Window
。但有一點要注意的是,如果是在嚴格模式下,this
為 undefined
。
如下程式碼範例,因為是一般函式調用,this
會是指向 Window
,所以第一個輸出結果是 Window
。而因為在全域範圍中用 var
定義 name
變數,因此, name
變數也會綁定到 Window
物件上,第二個輸出結果也等同於 window.name
的值。(備註,如果是用 let
定義,並不會綁定在 Window
物件上。)
var name = "John";
function callThis() {
console.log(this);
console.log(this.name);
}
callThis();
// Window
// John
2. 物件方法調用
當一個函式是做為一個物件的方法來調用時,this
會指向這個物件。
const john = {
name: "john",
callJohn() {
console.log(`hello, ${this.name}`);
},
};
john.callJohn(); // hello, john
3. 構造函式調用
當一個函式用 new
關鍵字調用時,此函式執行前會先創造一個新的物件,this
會指向這個新組成的物件。
如下面程式碼例子所示,最後呼叫結果為 Apple
。這是因為當構造函式 Cellphone
被 new
調用時,會先創造一個新的物件,讓 this
會指向這個新物件,=在這個例子中,就印出了這個新物件的 brand
是 Apple
。
function Cellphone(brand) {
this.brand = brand;
}
Cellphone.prototype.getBrand = function () {
return this.brand;
};
let newIPhone = new Cellphone("Apple");
let newPixelPhone = new Cellphone("Google");
console.log(newIPhone.getBrand()); // Apple
console.log(newPixelPhone.getBrand()); // Google
4. apply、call、bind 方法調用
我們也可以使用 apply
、call
、bind
方法來指定 this
指向的物件。
apply
方法接受兩個參數,第一個是 this 綁定的對象,第二個會放入要傳入函式的陣列參數,並執行此新函式。call
方法類似為apply
,唯一不同的地方是,apply
第二個參數是陣列,但call
則是依序放在後面。bind
方法透過傳入一個物件和要傳入的參數,不同於apply
和call
,bind
不會立即執行此心函式,而是會返回此新函式。
function getBrand(prefix) {
console.log(prefix + this.brand);
}
let apple = {
brand: "Apple",
};
let sony = {
brand: "Sony",
};
getBrand.call(apple, "It's a "); // It's a Apple
getBrand.call(sony, "It's an "); // It's an Sony
5. 箭頭函式中的 this
ES6 中介紹了一種新的函式型態 - 箭頭函式(arrow function)。但要注意的是,箭頭函式並沒有屬於自己的 this
值,箭頭函式的 this
會從他的外在函式繼承,若他的外在函式也同為箭頭函示,則回繼續往上尋找,直到找到全域環境的預設 this
值(例如:瀏覽器中就是 window
)。
let getThis = () => this;
console.log(getThis() === window); // true