---
# System prepended metadata

title: What is "this"?
tags: [JavaScript, this]

---


# What is "this"?
>editor: Jung
>environment：node.js 14.7.2

## 簡單介紹
:::info
當在不是物件導向的環境下，this的預設值會是global，那這個global取決於你在什麼環境下面。

譬如當我在node.js下面跑下面這一個test的function，它的this是一個叫做global的變數。

但當你在瀏覽器上面跑的話，this就會是window。依據環境的不同，this的值也會不同。但它都是global的東西（一個全域的東西）。
```javascript=
function test () {
    console.log(this) // 預設值會是 global
    console.log(this === global) // 在node.js 下面執行會是 true
    console.log(this === window) // 在瀏覽器下面執行會是 true
}

test()
```
:::
:::warning
當在嚴格模式下，this會是undefined。
當在嚴格模式與寬鬆模式下，它預設的this是不一樣的。

```javascript=
/* 可以試著在上面的程式碼加上下面這一行，看看會有什麼不同*/
'use strict'; // 嚴格模式
```
:::

## 有幾種情形例外
:::info 
譬如說你在操作DOM的時候
```javascript=
document.querySelector('.btn').addEventListener('click', function(){
    console.log(this) // 這邊是你實際點擊的按鈕
})
```

下面又是一個不一樣的例子，當我今天呼叫obj.test()，我們可以看到印出來的this就是obj本身。

this的值在它跟你的程式碼在哪裡定義無關，它跟你怎麼去呼叫有關。
舉個例子，這邊可以看到obj2()他的this居然是undefined，不是同一個funciton嗎，為什麼他的竟然不一樣。

這邊提供一下幾個基本原則讓你可以知道this的值
>- 在根本跟物件無關的地方call this，它就會是undefined或是window，看你當時的環境跟是不是嚴格模式。
>- 當你在物件導向的時候call this，它就會是自己的instance。
>- 在物件的情況下call this。譬如說下面寫的obj的test function，它則是被怎麼樣被呼叫有關係。
```javascript=
'use strict';
const obj = {
    num: 123,
    test: function() {
    console.log(this)
    }
}
obj.test()

const obj2 = obj.test
obj2() // undefined or global/window
```
:::
## arrow function 的 this
:::info
箭頭函式的特性，它的特性是什麼呢？箭頭函式裡面的this，它跟你怎麼呼叫沒有關係，它是唯一的特例。它跟你定義在程式碼的哪裡有關，它會去用它定義的時候的那邊的那個this的值（很拗口 ＸＤ）有關係。
:::
```javascript=
let obj = {
    num: 123,
    test: function () {
        console.log(this)     // obj本身
        setTimeout(() => {
            console.log(this) // obj本身
        },100)
    }
}
obj.test()

let obj２ = {
    num: 123,
    test: function () {
        console.log(this)     // obj本身
        setTimeout( function() {
            console.log(this) // undefined or global/window
        },100)
    }
}
obj２.test()


// 這一段一樣意思 看不懂沒關係因為這邊要知道 ES6 Class(類別的概念)
class Test {
    run() {
        console.log('run this',this)
        setTimeout(function() { // 也可以試試看改成箭頭函式
            console.log(this) 
        },100)
    }
}
const t = new Test()
t.run()
```

## call & apply & bind 下集待續



###### tags: `JavaScript` `this`