---
# System prepended metadata

title: 箭頭函式與 this(上)
tags: [' hexo部落格', JavaScript]

---

---
tags:  JavaScript, hexo部落格
title: 箭頭函式與 this(上)
---

## 箭頭函式 (Arrow functions)
與一般函式相比，寫法更加簡潔，也避免了某些問題。
```javascript
// 一般函式寫法
function fn(){
  console.log('此為具名函式 - 函式陳述式寫法。')
}
var a = function(){
  console.log('此為匿名函式 - 函式表達式寫法。')
}

// 箭頭函式
const b = () => {
  console.log('此為箭頭函式寫法。')
}
// 若函式只有單一變數，參數括號可以簡化
const c = str => {
  str = '簡化參數括號'
  console.log(str)
}

// 若函式內只有單一陳述行，大括號可以簡化，但沒有參數時，括號必須存在
const d = () => console.log('此為箭頭函式簡易寫法。')
```
### 箭頭函式與一般函式的差異
箭頭函式除了寫法簡潔之外，它跟一般函式有甚麼差異? 每當搜尋相關介紹時，總會說明它沒有這些 : 
- `this`
- `arguments` 
- `call()`
- `apply()`
- `bind()`

而這些到底是甚麼? 為什麼那三個內建函式又是甚麼? 為什麼它們看起來很陌生? 在下集會來介紹，在上集中會先介紹 `this`。

先簡易說明一下，`call()`、`apply()`、`bind()` 這三種 JS內建函式，可以影響 `this` 的運作，若使用箭頭函式的話，由於 ES6的規則，連帶的那三個函式也跟著無法使用。
而 `arguments`，它為一般函式的內建參數，在箭頭函式中無此內建參數可運用，但是可以改用 ES6的其餘參數來達到同樣效果。

## this
看到箭頭函式的介紹時，常會看到一句話，箭頭函式沒有自己的`this`，而 this從何而來，又指向誰，為什麼會用到它? 

### this是甚麼 ?
- this 是 JavaScript的內建關鍵字之一
- 通常會用在函式或物件中，來呼叫自身的擁有的屬性或值等等...

### this從何而來 ?
先來看個範例 : 
```javascript 
var a = 1
console.log(a) // 1
console.log(window.a) // 1
console.log(this.a) // 1
```

當我們將瀏覽器打開時，就已經建立好全域環境與執行環境，而程式碼就是寫在執行環境中，而 `this` 與全域環境一起被建立。
- 全域環境
- `this`
- 執行環境

當我們要呼叫 a這個變數時，由上述範例可以知道，有三種呼叫變數 a的方式 :
- 直接呼叫
- 透過全域物件呼叫
- 透過 JS 內建關鍵字 `this` 呼叫

變數 a 是由 var 宣告的，而它的執行環境在全域環境中，於是變數 a 就被建立在全域環境，接著就能透過全域物件 window 找到它。

### this指向誰 ?
通常我們寫程式碼時，習慣在全域環境下作業，而 `this` 在呼叫自身時，**必須留意在哪個環境被呼叫，而不看在哪裡被使用**，像是以下這些例子 :
* 簡易呼叫函式
```javascript=
// 在全域的環境下執行函式，`this`會呼叫全域下的變數
var name = '全域阿婆'
function nameFn(){
  var name = '漂亮阿姨'
  console.log(this.name);
}
nameFn() // '全域阿婆'
```
* 物件中呼叫函式
```javascript=
// 在全域的環境下執行物件中的函式，`this`則指向物件本身
const obj ={ 
  name:'小杰',
  callFn(){ // 物件內函式縮寫
    console.log(this.name);
  }
}
obj.callFn(); // '小杰'
```
* 物件裡呼叫函式並執行函式中的函式
```javascript=
var name = '全域阿婆';
const obj = { 
  name:'小杰',
  callFn(){ // 物件內函式縮寫
    function callFn2(){
      console.log(this.name);
    };
    callFn2();
  }
}
obj.callFn(); // 相當於直接執行 callFn2() -> '全域阿婆'
```
### 為什麼會用 this ?
在 `this` 一開始有提到，它可以用在函式或物件中，來呼叫自身的擁有的屬性或值，來看以下例子 : 
```javascript=
let personA = {
  age: 18,
  sayHello: function (number){
    console.log(`我今年${number}歲`)
  }
}
personA.sayHello(personA.age)

let personB = {
  age: 10,
  sayHello: function (){
    console.log(`我今年${this.age}歲`)
  }
}
personB.sayHello()
```
使用 `this` 可以讓程式碼簡化不少。


## 箭頭函式與 this
上述範例中，物件裡呼叫函式並執行函式中的函式，`this` 會指向全域，而我們可以使用箭頭函式來解決這樣的問題，因為 : 
- 箭頭函式沒有自己的 `this`
- 當箭頭函式中使用 `this` 時，它會往上一層尋找
- 也就是說，**在哪邊被使用，它就會往上一層尋找，而不看環境**

```javascript=
let name = '全域阿婆'
const obj = { 
  name:'小杰',
  callFn () { // 物件內函式縮寫
    const callFn2 = () => {
      console.log(this.name);
    }
    callFn2();
  }
}
obj.callFn(); // '小杰'
```

## 回想
- 箭頭函式怎麼寫 ?
- 如何知道箭頭函式沒有自己的 `this` ?
- 甚麼時候會用到 `this` ?
- `this` 在不同地方會指向誰 ?
    - 在全域環境下，若創造一個箭頭函式並使用了 `this` ，它會指向誰 ?
    - 在物件中新增了一個函式並使用了 `this` ，最後在全域環境下呼叫物件內的函式，它會指向誰 ?
 


## 參考來源
> 1. [Schaos - 前端三十｜10. [JS] 一般函式與箭頭函式的差異？](https://medium.com/schaoss-blog/%E5%89%8D%E7%AB%AF%E4%B8%89%E5%8D%81-10-js-%E4%B8%80%E8%88%AC%E5%87%BD%E5%BC%8F%E8%88%87%E7%AE%AD%E9%A0%AD%E5%87%BD%E5%BC%8F%E7%9A%84%E5%B7%AE%E7%95%B0-32ce9455ff1a)
> 2. [胡立 - 淺談 JavaScript 頭號難題 this：絕對不完整，但保證好懂](https://blog.techbridge.cc/2019/02/23/javascript-this/)
> 3. [Mooji - JS 原力覺醒 Day07 - 陳述式 表達式](https://ithelp.ithome.com.tw/articles/10218937)
> 4. [卡斯伯 - 鐵人賽：箭頭函式 (Arrow functions)](https://wcc723.github.io/javascript/2017/12/21/javascript-es6-arrow-function/)
> 5. [MDN - 箭頭函式](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
> 7. 六角學院 - JS核心篇
