# this in arrow function
---
## 什麼是this
- 在函式內,this 值取決於如何呼叫該函式[MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/this)
- 如果一個函式是以物件的方法呼叫,它的 this 會被設為該呼叫函式的物件。
---
## this in Arrow Function
- 在過去,函數的 this 變數在不同狀況下一直指向不同值,這樣的特性對物件導向程式設計來說其實相當麻煩。[MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- 這句話吸引我了,我也覺有點困擾==
----
### 範例
- 本來想寫一個function,每秒增加一歲, 不是arrow function的寫法
```JavaScript
function Person() {
this.age = 0;
setInterval(function growUp() {
this.age++;
// console.log(this.age)
}, 1000);
}
var p = new Person(); //結果setInterval的this是window...@@
```
[CodePen](https://codepen.io/TengLee/pen/QOJeNx)
----
### 執行的物件 !== 定義的物件
- 因為它執行的環境會變成是 global environment,因此使用傳統函式時,這個 this 指稱的對象會轉變成 window object 。
- 結果,用這個做法this.age++ 無法每秒加一歲
- 那怎麼辦...
----
### 使用閉包closure
- 利用 closure 將 this 變數存入另一個變數之中
```JavaScript
function correctPerson() {
var self = this;
self.age = 0;
setInterval(function growUp() {
console.log("q: " , self)
self.age++;
}, 1000);
}
var q = new correctPerson();
```
----
### 主角出場!!!
- 也可以用arrow function!
```JavaScript
function arrowPerson(){
this.age = 0;
setInterval(() => {
console.log("r: " , this)
this.age++;
}, 1000);
}
var r = new arrowPerson();
```
- **箭頭函數會自動將 this 變數綁定到其定義時所在的物件**[MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- 直白一點:箭頭函數當中的 this 是定義時的對象,而不是使用時的對象[PJchen](https://pjchender.blogspot.tw/2017/01/es6-arrow-function.html)
----
### 你以為這樣就沒事了嗎?
- 看下面兩個例子
---
### this在arrow function要注意的地方之一
<br>
### 例子一 將箭頭函數撰寫為method
- arrow function expressions are **best suited for non-method functions**. ~by MDN~
----
### 什麼是method function
- method 是個屬於object property的function, Methods 跟定義一般function一樣,但他們必須是屬於object的property [MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Working_with_Objects)
```JavaScript
objectName.methodname = function_name;
var myObj = {
myMethod: function(params) {
// ...do something
}
};
```
----
```JavaScript
var obj = {
i: 10,
b: function() {
console.log(this.i, this);
},
c: () => console.log(this.i, this)
}
obj.b(); // prints 10, obj
obj.c(); // prints undefined, window
```
- 這裡的arrow function的this會被定義為global object
- arrow functions assume the this of the **lexically enclosing function context**, the this within an object definition is either the window or something else. [stack overflow](https://stackoverflow.com/questions/31095710/methods-in-es6-objects-using-arrow-functions)
----
#### this在arrow function要注意的地方之二
#### 如果定義和呼叫物件不同呢?
<br>
## 監聽事件
<br>
#### addEventListener
----
```JavaScript
var button = document.querySelector('button');
var fn_arr = () => {
// 建立 function 時 this 指 Window
console.log(this.constructor.name) // 執行function時 this 指 Window
};
var fn = function(){
// 建立 function 時 this 指 Window
console.log(this.constructor.name) // 執行function時 this 指 HTMLButtonElement
button.addEventListener('click', fn_arr);
```
[JsBin](https://jsbin.com/kotetu/edit?js,output)
----
- 和setTimeout 類似,我們使用的 addEventListener ,也會在整個 execution context 執行結束後,在網頁觸發事件時才執行。
- 函式建立的時間和實際執行的時間是不同的,因此這也創造了兩個不同時間點的 this 所指稱的對象。
---
## 總結
- 箭頭函式並不是完全只是原本JS中函式的縮寫語法而已,它與原本的函式內部設計有些不同。
- 箭頭函數會自動將 this 變數綁定到其定義時所在的物件
- 在傳統的函數,可以用閉包,var self = this
- arrow function的this 不要用在object method
- 注意定義的物件和執行的物件有可能會不一樣
- **如果不確定this會指稱到什麼,就console.log出來**
---
### 補充
- 物件裡的值如果是原生值(primitive type;例如,字串、數值、邏輯值),我們會把這個新建立的東西稱為「屬性(property)」;如果物件裡面的值是函式(function)的話,我們則會把這個新建立的東西稱為「方法(method)」。[PJchen](https://pjchender.blogspot.tw/2016/03/javascriptthisbug.html)
- [談談JavaScript中的"this"和它的bug](https://pjchender.blogspot.tw/2016/03/javascriptthisbug.html)
- The most common use case for arrow functions is as short "lambdas" which do not redefine this, often used when passing a function as a callback to some function.
[stack overflow](https://stackoverflow.com/questions/31095710/methods-in-es6-objects-using-arrow-functions)
{"metaMigratedAt":"2023-06-14T15:08:20.169Z","metaMigratedFrom":"Content","title":"this in arrow function","breaks":true,"contributors":"[]"}