搞懂Javascript的this

前言

在Javascript程式語言中,常面臨到this,但也很常搞不太清楚this指向的對象是誰,而造成程式的一些bug,透過這篇文章來釐清並整理一下this的觀念,以下將用各情境來說明。


情境1-直接宣告this

1
2
console.log(this) //Window

會發現無任何包裝,直接印出this,會指向Window物件

情境2-獨立函式內的this

1
2
3
4
function testFn(){
console.log(this); //Window
console.log(this.innerWidth); //可以印出視窗的寬度
}

獨立函式內的this也是指向Window物件

情境3-物件方法內的this

1
2
3
4
5
6
7
8
let person = {
name: "Fred",
say: function () {
console.log(this); //person物件本身
console.log(this.name); //Fred
}
}
person.say();

可以看出物件方法內的this就是物件本身,所以也能因此再找出其他屬性或方法,如name屬性,就印出Fred。
這時候我們來實驗一下,把傳統function改為箭頭函式會發生什麼事情呢?

1
2
3
4
5
6
7
8
let person = {
name: "Fred",
say: () => {
console.log(this); //Window
console.log(this.name); //undefined
}
}
person.say();

這時候發現this竟然會印出Window物件,為什麼呢?因為如果用箭頭函式,就沒有自己的this,所以如果在箭頭函式內沒有找到this變數,就會往外找,就直接找到Window物件,所以也因為Window沒有name的屬性,自然this.name就印出undefined了。所以使用箭頭函式時要特別注意一下這個觀念。

情境4-事件處理function

1
2
3
4
document.addEventListener("click", function () {
console.log(this); //document元素
this.body.innerHTML = "我被點到了";
})

this就是觸發事件的對象物件,像上述範例來說,就是document元素。
若改為箭頭函式,會發生什麼事呢?

1
2
3
4
document.addEventListener("click", () => {
console.log(this); //Window
this.body.innerHTML = "我被點到了";
})

在情境3時我們有提到箭頭函式沒有自己的this,所以函式內的this就是往外找,也找到了Window物件,因此,如果我們點一下畫面會直接報錯Uncaught TypeError: Cannot set properties of undefined (setting ‘innerHTML’)

情境5-建構函式(Constructor Function)

1
2
3
4
5
6
7
function Person() {
console.log(this); //{}
this.name = "Fred";
this.age = 18;
}
let p1 = new Person();
console.log(p1); //{age: 18,name: "Fred"}

這個範例可以發現第2行的this印出來是Person空白物件,不是一般物件。


小結

在做專案的時候常常因為追求語法閱讀與簡潔所以常會用到this,但往往沒有搞懂一些概念而造成意外的bug發生,如果再加上箭頭函式的觀念也沒有搞清楚的話,除錯起來也是很辛苦的,所以特別將this用法整理出來,也提醒自己要留意this的指向。