this 是一個關鍵字,在物件導向語言中表示對當前物件的引用。在 JavaScript 中,this 的值是動態的,它會指向某個物件,但具體指向哪一個物件取決於使用方法。
this 指向誰
在 JavaScript 中,this 是在函式被呼叫的時候決定的。也就是說,函式怎麼呼叫,決定了 this 指向誰。
第一種:普通函式直接呼叫 (預設綁定)
當函式不屬於任何一個物件,直接呼叫函式的話:- 非嚴格模式下,
this會指向全域物件 - 嚴格模式下,
this則是undefined
function sayHi(){
console.log(this);
}
sayHi();
輸出結果

瀏覽器在非嚴格模式下,直接呼叫函式的 this 會屬於 window

node.js 在非嚴格模式下,直接呼叫函式的 this 會屬於 global

瀏覽器在嚴格模式下,直接呼叫函式的 this 會是 undefined

node.js 在嚴格模式下,直接呼叫函式的 this 會是 undefined
第二種:函式做為物件方法被呼叫 (隱式綁定)
這是前一篇文章的物件範例:
const person ={
name: "Elaine",
age: 18,
// 方法的縮寫
sayHi(){
console.log("Hi");
}
}
我們現在把 sayHi() 改寫成:
const person ={
name: "Elaine",
age: 18,
// 方法的縮寫
sayHi(){
console.log(`Hi, I'm ${this.name}.`);
}
}
person.sayHi(); // Hi, I'm Elaine.
在這個例子中,sayHi() 由 person 這個物件呼叫,所以 this 會指向 person,因此可以取得 this.name = "Elaine"。
第三種:使用 new 呼叫建構函式 ( new 綁定)
一樣是在前一篇文章有提到的內容:
function Person(name, age, height, weight){
this.name = name;
this.sayHi = function(){
console.log("Hi");
}
}
// 使用 new 運算子建立 instance
const person1 = new Person("Elaine");
使用 new 呼叫函式時,this 會被綁到新建立的物件實例上,這裡的 this 就會指向 person1。
第四種:html DOM 事件中的事件處理機制
Html 事件中,this 會綁定接收事件的元素,以這個例子來說,this 就綁訂了這個 button 元素。
<html>
<head>
<title> Html this 測試</title>
</head>
<body>
<button id = "mybtn">點我</button>
</body>
<script>
const button = document.getElementById("mybtn");
button.addEventListener("click", function(){
console.log(this);
});
</script>
</html>
第五種:使用 call()、apply()、bind() 綁定 this (顯示綁定)
// 定義物件
const person = {
greet: function(city, country){
console.log(`My name is ${this.firstName} ${this.lastName}. I'm from ${city}, ${country}.`);
}
}
// 定義函式
function age(){
console.log(`My age is ${this.age} years old.`);
}
const girl = {
firstName: "Elaine",
lastName: "Wang",
age: "23"
}
Call():用來指定this指向誰,並執行function或是其他物件的方法,返回值為函式執行結果。
// 使用 call 將 this 綁定到 girl 物件,並呼叫 person 物件的方法
person.greet.call(girl, "New York", "USA"); // My name is Elaine Wang. I'm from New York, USA.
// 使用 call 將 this 綁到 girl 物件,並呼叫函式 age
age.call(girl); // My age is 23 years old.
apply():用法與call()基本上相同,只差在call()將參數視為個別,而apply()將參數視為一個 array,返回值為函式執行結果。
// 使用 apply 將 this 綁定到 girl 物件,並呼叫 person 物件的方法
person.greet.apply(girl, ["New York", "USA"]); // My name is Elaine Wang. I'm from New York, USA.
// 使用 apply 將 this 綁到 girl 物件,並呼叫函式 age
age.apply(girl); // My age is 23 years old.
// 使用 apply 模擬其他方法,array 本身沒有 max 方法,可以用 apply 借用
console.log(Math.max.apply(null, [1,2,3,4])); // 4
bind():用法與call()基本上相同,不一樣的是 bind 的返回值為新的函數,且這個綁定的 this 是永久綁定。
// 先新增另一個物件
const boy = {
firstName: "Tom",
lastName: "Lin",
age: "25"
}
// 使用 bind 將 this 綁定到 boy 物件,並返回新的方法
const boy_greet = person.greet.bind(boy, "Tokyo", "Japan");
boy_greet(); // My name is Tom Lin. I'm from Tokyo, Japan.
const boy_age = age.bind(boy);
boy_age(); // My age is 25 years old.
setTimeout 與 setInterval 的 this 陷阱
我們在 person 物件中新增一個方法 sayMyName,並用 setTimeout 定時一秒。
const person = {
name:"Elaine",
greet: function(city, country){
console.log(`My name is ${this.firstName} ${this.lastName}. I'm from ${city}, ${country}.`);
},
sayMyName(){
setTimeout(function(){
console.log(this.name);
},1000);
}
}
person.sayMyName(); // 輸出 undefined
為什麼這邊的 sayMyName 會輸出 undefined 呢?
前面說到「 this 是誰,取決於函式如何被呼叫」:
person.sayMyName()這行被呼叫時,this指向呼叫他的物件,也就是 person。- 但是
setTimeout(function(){...}, 1000)裡面的 function 是setTimeout在一秒後以普通函式的形式呼叫的,所以會套用預設綁定的規則。
這個狀況在 setInterval 也是一樣的! 需要特別注意。那這種狀況要怎麼解決呢? 最推薦的做法是使用箭頭函式。
箭頭函式在【JavaScript 入門:JS 的函式解析! 宣告式、表達式、箭頭函式】有介紹,忘了的朋友可以回去回顧一下~
箭頭函式與 this
在【JavaScript 入門:JS 的函式解析! 宣告式、表達式、箭頭函式】裡,其實已經提到過了 this,但是當時並沒有詳細的說明。
當時我們說到箭頭函式與其他函式的 this 規則不同,實際上,箭頭函式並沒有自己的 this,他的 this 會從外層作用域繼承。也就是說,箭頭函式在建立時就會捕捉當價作用域的 this,而不是在呼叫時才決定。
所以我們可以將上面 setTimeout 的範例改成:
const person = {
name:"Elaine",
greet: function(city, country){
console.log(`My name is ${this.firstName} ${this.lastName}. I'm from ${city}, ${country}.`);
},
sayMyName(){
setTimeout(()=>{
console.log(this.name);
},1000);
}
}
person.sayMyName(); // 輸出 Elaine
這裡的 person.sayMyName 可以輸出 Elaine 是因為箭頭函式從外層繼承了 this。
參考
- 解釋 JavaScript 中 this 的值?
- JavaScript this 关键字
- JavaScript 入門:物件 (Object )是什麼、要怎麼建立?
- JavaScript 入門:JS 的函式解析! 宣告式、表達式、箭頭函式













