# this
指向某個建構子 (constructor) 所建立的物件。但事實上在 JavaScript 裡面, this 所代表的不僅僅是那個被建立的物件。
預設綁定會在callback的this指定給Global Object (Window 物件)
> 透過 addEventListener 註冊了 click 事件,事件中的 this 指的是「觸發事件的元素」。
> 要是我們在事件的 callback function 加入 ajax 的請求,那麼根據前面所說的,預設綁定 (Default Binding) 會把這個 callback function 的 this 指定給 global object,也就是 window。
```javascript=
el.addEventListener("click", function(event) {
// 透過 that 參考
var that = this;
console.log( this.textContent );
$ajax('[URL]', function(res) {
// this.textContent => undefined
console.log(that.textContent, res);
});
}, false);
```
像這樣,我們將事件內的 this 先用一個叫 that 的變數儲存它的參考,那麼在 ajax 的 callback function 就可以透過 that 來存取到原本事件中的 this 了。
### 強制指定 this 的方式
#### bind(),call(),apply()
`bind():`
```javascript=
el.addEventListener("click", function(event) {
console.log( this.textContent );
// 透過 .bind(this) 來強制指定該 scope 的 this
$ajax('[URL]', function(res) {
console.log(this.textContent, res);
}.bind(this));
}, false);
```
* bind()讓這個function在呼叫前先綁定某個物件,使他不管怎麼被呼叫都能有固定的this。
* 尤其常用像是在callback function這種類型的場景,看想像是先綁定好this,然後讓function在需要時被呼叫的類型。
* .call() 與 .apply()依造呼叫時的需要帶入不同的物件作為該function的this。
* 使用在context較常變動的場景。
```javascript=
var list = [1, 5, 8];
function add() {
return Array.from(arguments).reduce(function(sum, num) {
return sum + num;
});
}
console.log(add.call(null, 1, 2));// 3
console.log(add.apply(null, list));// 14
```
### this 與前後文本 (context) 綁定的基本原則
#### 預設綁定 (Default Binding)
宣告在全域範疇 (global scope) 的變數,與同名的全域物件 (window 或 global) 的屬性是一樣的意思。
因為預設綁定的關係,當 function 是在普通、未經修飾的情況下被呼叫,也就是當 function 被呼叫的當下如果沒有值或是在 func.call(null) 或 func.call(undefined) 此類的情況下,此時裡面的 this 會自動指定至全域物件。
但若是加上 "use strict" 宣告成嚴格模式後,原本預設將 this 綁定至全域物件的行爲,會轉變成 undefined。
#### 隱含式綁定 (Implicit Binding)
指的是,即使 function 被宣告的地方是在 global scope 中,只要它成為某個物件的參考屬性 (reference property),在那個 function 被呼叫的當下,該 function 即被那個物件所包含。
```javascript=
function func() {
console.log( this.a );
}
var obj = {
a: 2,
foo: func
};
func(); // undefined
obj.foo(); // 2
```
```javascript=
function func() {
console.log( this.a );
}
var obj = {
a: 2,
foo: func
};
obj.foo(); // 2
var func2 = obj.foo;
func2(); // undefined
```
:::warning
**決定 this 的關鍵不在於它屬於哪個物件,而是在於 function「呼叫的時機點」**
:::
這個 function 的呼叫,是透過 new 進行的嗎? 如果是,那 this 就是被建構出來的物件。
這個 function 是以 .call() 或 .apply() 的方式呼叫的嗎? 或是 function 透過 .bind() 指定? 如果是,那 this 就是被指定的物件。
這個 function 被呼叫時,是否存在於某個物件? 如果是,那 this 就是那個物件。
如果沒有滿足以上條件,則此 function 裡的 this 就一定是全域物件,在嚴格模式下則是 undefined。
[重新認識 JavaScript: Day 20 What's "THIS" in JavaScript (鐵人精華版)](https://ithelp.ithome.com.tw/articles/10193193)
[談談 JavaScript 中的 "this" 和它的問題](https://pjchender.blogspot.com/2016/03/javascriptthisbug.html)