---
# System prepended metadata

title: this

---

# 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)