---
# System prepended metadata

title: Arrow Function 箭頭函式

---

# Arrow Function 箭頭函式 & 內部的 this

Arrow function expression 可以說是原型function expression的一個簡潔寫法的替代方案，但是在使用上有一些限制和語法上的不同。

* 箭頭函式不具備自己的'this', 'arguments' 或 'super' 綁定，而且不適合用作於物件的方法
* 箭頭函式不可以使用 Constructors，如果使用 new 方法呼叫他們，會拋出 TypeError 的錯誤。
* 箭頭函式無法在主體內使用 "yield"，並且也無法使用 generator function。

## 箭頭函式的基本語法 
const sum = function(a,b) => a + b

## 不具備自己的 'this', 'arguments' 或 'super' 綁定

```javascript=

// 箭頭函式的基本語法

const sum = function(a,b) => a + b

// 不具備自己的 this 綁定

const obj = {
    value: 10
    getValue: () => {
        // 在箭頭函式內的 this 會指向外部的作用域，而不是 obj
        return this.value
    }
}

console.log(obj.getValue()) 
// 在這裡 this.value 會是 undefined，因為箭頭函式內並沒有自己的this 綁定
```

```javascript=
// 不具備自己的 arguments 綁定
const printArguments = () => {
    // 箭頭函式內的 arguments 會參考到作用域外部的 arguements
    // 而不是函數自己的 arguments
    console.log(arguments)
}

// 此處會得到 Uncaught ReferenceError: arguments is not defined 
printArguments(1,2,3)

```

```javascript=
// 不具備自己的 super 綁定
class Parent{
    constructor(){
        this.name = "Parent"
    }
    printName = () => {
        // 箭頭函數內部沒有自己的 super綁定，所以無法使用 super
        console.log(this.name)
    }
}

const child = new Parent()
child.printName()
// 箭頭函式內的 this 就會指向外部作用域的 this，會正確印出 "Parent"

```
[MDN super的用法](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/super)

## 異步函數內使用的箭頭函式

**使用一般函式和箭頭函式方法的比對**

**一般函式的用法:** 這裡的 function 會綁定自己的 this，當這些函數被作為回乎傳遞給 fetch 的 "then" 方法時，可能會不正確，因為它會取決於被呼叫的上下文。

**箭頭函式的用法:** 不具備自己的 "this" 綁定，而是繼承外部作用域的 "this"，在這裡就會是跟 fetchData 函數的 "this" 一致，這使得箭頭函式內部的 "this" 就會自然而然地保留外部作用域的 "this"，而不會受到 **.then 方法內部的綁定問題**的影響。

```javascript=

// 一般函式

function fetchData(){
    fetch('https://api.example.com/data')
      .then(function(response){
        // 這裡的 this 可能會有問題，因為是來自於 fetch 回呼函式產生的，這裡的 function 會綁定自己的 this。
        return(response.json())
    })
      .then(function(data){
        // 同樣的問題也會發生在這裡
        console.log(data)
    })
}

// 箭頭函式的用法
function fetchData(){
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => console.log(data))
}

```

## 重新認識 "this" & 箭頭函式內部的 "this" 用法

this 是 object 正在執行 function 的一個參考值

1. method -> obj
    如果 function 是一個物件的方法，那 "this" 指向的就是 obj
2. function -> global (window, global)

```javascript=

const video = {
    titel: "a",
    play(){
      console.log(this)
    }
}

video.stop = function(){
    console.log(this)
}

video.play()
video.stop()

function playVideo(){
    console.log(this)
}

// normal function 印出來就會是 WINDOW OBJECT
playVideo()


// constructor function
function Video(title){
  this.title = title
  console.log(this)
}

const v = new Video("b")  // 在這裡 new 會 create 一個空物件 {}，並將 title 帶入。

```

video.play() 和 video.stop() 都會指向 video obj

![image](https://hackmd.io/_uploads/HJZGT15i6.png)

若是普通的function: playVideo 函式印出來的 this，就會是 window object。

![image](https://hackmd.io/_uploads/BJXtaJ9i6.png)

constructor function Video 印出來的 this
![image](https://hackmd.io/_uploads/HJ2N21qi6.png)


function 內部不同的 this 指向問題:

```javascript=

const video = {
    title: "a",
    tags: ["a", "b", "c"],
    showTags(){
        // 在 showTags method 裡指向 video obj ，抓取 tags 屬性的值，使用 forEach 方法。
        // forEach 方法若如下使用普通 function，會有自己的this，在這裡就會顯示錯誤，因為這裡 this 指向的就是 window object。
        this.tags.forEach(function(tag){
            console.log(this.title, tag)
        })
    }
}

// 這裡解決 forEach 內部 console.log 出現 undefined 的問題其中兩個方式: 

// 1. 加入 forEach 的第二個參數 thisArg

forEach(callbackFn, thisArg)

// 在 showTags 方法內部，可以在 forEach 的第二個參數放入 "this" 
this.tags.forEach(function(tag){
            console.log(this.title, tag)
        }, this)

// 2. 直接改成箭頭函式: 直接抓取外部作用域的 "this"，也就是 video 的 obj

this.tags.forEach((tag) => console.log(this.title, tag))

```

使用一般函式內部印出來的 this.title 產生的問題，小心就會變成 undefined 錯誤

![image](https://hackmd.io/_uploads/SkZkEx5sp.png)


## 參考資料
* [MDN Arrow Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) 
* [JavaScript this Keyword](https://www.youtube.com/watch?v=gvicrj31JOM)

