0%

箭頭函式與this

箭頭函式與this
首先,箭頭函式有以下幾種特性

  1. 超簡潔的寫法
  2. this變數的強制綁定
    而箭頭函式的的this變數綁定的方式有跟傳統的function不一樣
    傳統函式: 呼叫該function時的物件
    箭頭函式: 綁定定義該箭頭函式時的物件

我們直接用一個含是裡面包另一個函式的範例來看看他們的差別

ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---傳統函式---
let obj = {
test: function(){
console.log(this); // 回傳obj物件

(function(){
console.log(this); // 回傳window物件
})();
}
}
obj.test();


---箭頭函式---
let obj = {
test: function(){
console.log(this); // 回傳obj物件

(()=>{
console.log(this); // 回傳obj物件
})();
}
}
obj.test();

來解釋一下為什麼內層函式回傳的值會不一樣。
首先,傳統函式
在外層的this回傳是obj物件,是因為呼叫test函式的物件是obj,所以,回傳obj物件。
而內層的話,是因為JavaScript的變數的最小區分單位是function,所以,在內部的立即函式的作用環境跟
外層是分隔開的,而它所擁有的this變數也是獨立的,而this變數的預設綁定是window物件,所以,最終結果才會回傳window物件。

接著,箭頭函式
外層的函式上面解釋過了,會回傳obj物件。
內層的話,會因為該立即函式被定義的時候,是在obj物件的環境下,所以,以箭頭函式定義的立即函式它的this變數會綁定obj,
而這也是為什麼它會回傳obj物件的原因。

———————我是分隔線——————————–
接下來,我來改寫一下上面的箭頭函式的範例
ex:

1
2
3
4
5
6
7
8
let obj = {
test: ()=>{
console.log(this); // 回傳window物件
(()=>{
console.log(this); // 回傳window物件
})();
}
}

我們將成員函式test也用箭頭函式的形式來定義它,
按照arrow function的特性,其this會綁定該arrow function被定義時的物件,
而物件obj在定義的時候,它是屬於window物件的其中一個屬性,所以,test的箭頭函式會綁定window物件,
而在test內層的IIFE也因為是在外層是window物件的狀態下定義的,故該IIFE的this會綁定window物件。

從上面的這些範例中,就要特別注意,你在使用arrow function在定義某函式時,其定義當下物件是誰,
如果,你有要在這個箭頭函式裡面使用this的變數的話。

———————我是分隔線——————————–
另外,特別紀錄一下,監聽是件如果也用arrow function來撰寫觸發事件的話,回傳的this也會和傳統函式不一樣
ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---傳統函式範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', function(){
console.log(this); // 回傳被點擊的按鈕物件
});


---箭頭範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', ()=>{
console.log(this); // 回傳window物件
});

</script>

來解釋一下
在傳統函式範例
該監聽函式的觸發事件是被button這個物件所觸發的,所以,this會是這個button物件。

在箭頭函式範例
該監聽函式的觸發事件是透過el變數來定義的,而el變數是window物件的其中一個屬性,所以,該監聽事件的箭頭函式
的this事綁定window物件。

———————我是分隔線——————————–
比較一下傳統函式在監聽事件 和 一般函式造成的this差別在哪
ex:

1
2
3
4
5
6
7
8
9
10
---傳統函式範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', function(){
console.log(this); // 回傳被點擊的按鈕物件
});

我在這邊順便為傳統函式加一範例,讓整個狀況更混亂XDD

ex:

1
2
3
4
let foo = function(){
console.log(this);
}
foo(); // 回傳window物件

我在看這個範例的時候,覺得跟上面用傳統函式來撰寫監聽事件的那個範例有點混淆,
來講一下this,this是代表”觸發該事件的人”
所以,在傳統函式來撰寫監聽事件的那個範例,觸發該事件的物件是那個按鈕物件,所以,this會綁定button物件。
而這邊這個範例,
我們是利用foo變數來呼叫函式,而變數foo是window物件的屬性,所以,其實是window物件觸發了該事件,
所以,該函式裡面的this才會是window。