【JavaScript】function,アロー関数どっち使ってる？違いをまとめてみた

# 結論から（比較表）

| 観点                   | `function` 構文                  | アロー関数 (`=>`)                     |
|------------------------|----------------------------------|---------------------------------------|
| **this の扱い**        | 呼び出し元に応じて動的に決まる       | 定義時の外側の this を固定的に使う     |
| **arguments 使用可否** | ✅ 使用可能                         | ❌ 使用不可（代わりに `...args` を使う） |
| **new での生成**       | ✅ コンストラクタとして使える         | ❌ new できない                        |
| **構文の簡潔さ**       | やや冗長                            | ✅ 簡潔に書ける                        |
| **return の省略**      | ❌ 必ず書く必要がある                | ✅ 単一式なら省略可能                  |
| **使いどころ**         | メソッド、イベント、クラスメソッドなど | コールバック、短い関数、非同期処理など  |

---

# 1.thisの扱いについて
`this`の扱いはfunctionとアロー関数で異なります。

### functionの場合
functionで定義した関数の`this`は呼び出しもとで動的に変わります。
```js:test.js
param = 'global param' //グローバル変数

function func() {
  console.log('function:', this.param)
}

obj = {
  param: 'local param',
  func: func
}

obj.func()   //'function: local param'
func()       //'function: global param'
```
### アロー関数の場合
```js:test2.js
param = 'global param'

const arrow = () => {
  console.log('arrow:', this.param)
}

obj = {
  param: 'local param',
  arrow: arrow
}

obj.arrow()  //undefined
arrow()      //undefined
```
あれ？アロー関数ではどちらも`undefined`になっていますね。
実はこれJavaScriptの仕様で`this`は`globalThis`に移行しました。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis

### 補足：thisとglobalThis
トップレベルで`const`,`let`,`var`をつけずに定義した変数はグローバル変数と呼ばれ、グローバルオブジェクトに格納されます。
Node.jsではグローバルオブジェクトは`this`ではなく`globalThis`に変更されました。(ブラウザではどちらもWindowオブジェクトを指します。)
```js:test3.js
params = 'global param'

console.log('this:', this)             //{}
console.log('globalThis:', globalThis) //...省略, param: 'global param'
```
話を戻すと、、、
アロー関数の挙動を調べるには`this`のパラメータを定義すれば良さそうですね！
test2.jsを変更
```js:test2.js
this.param = 'global param' //thisというオブジェクトにparamを格納

const arrow = () => {
  console.log('arrow:', this.param) 
}

obj = {
  param: 'local param',
  arrow: arrow
}

obj.arrow()  //'arrow: global param'
arrow()      //'arrow: global param'
```
アロー関数では呼び出し方に関わらず`this`オブジェクトが参照されることがわかりました。

---

# 2.arguments オブジェクトの違い
```js:test4.js
function func() {
  console.log(arguments) // 利用可能
}

const arrow = () => {
  console.log(arguments) // 利用不可
}
func(1,2,3) // [Arguments] {'0': 1, '1': 2, '2': 3}
arrow(1,2,3) //グローバルargumentsが参照される
```
アロー関数では、代わりに残余引数が使えます。
```js:test5.js
function func(...arguments) {
  console.log(arguments) // 利用可能
}

const arrow = (...arguments) => {
  console.log(arguments) // 利用可能
}
func(1,2,3) // [1, 2, 3]
arrow(1,2,3) // [1, 2, 3]
```
---
# 3.コンストラクタとして使えるか
```js:test6
function Person(name) {
  this.name = name
  console.log(this.name)
}
const p = new Person("Yuta") // 'Yuta'

const ArrowPerson = (name) => {
  this.name = name
  console.log(this.name)
};
// const p2 = new ArrowPerson("Yuta") //TypeError: ArrowPerson is not a constructor
```
---
# 4.returnの省略
```js:test7.js
function add(a, b) {
  return a + b
}

const add2 = (a, b) => a + b
```
アロー関数はブロック`{}`を使わない場合、暗黙的に`return`になります。

# 使い分け早見表

| シーン・目的                     | おすすめ構文   | 理由・補足説明 |
|----------------------------------|----------------|----------------|
| オブジェクトのメソッドを定義する     | `function`     | `this` がオブジェクト自身を指すため。アロー関数だと `this` がズレる |
| クラスのメソッド                  | `function`     | `this` や `super` を使いたいから |
| コンストラクタ（newする関数）      | `function`     | アロー関数は `new` できないため |
| コールバック（配列操作、非同期）   | アロー関数     | `this` に影響されず、短く書けて可読性が高い |
| 短い関数や一時的な処理           | アロー関数     | `return` を省略でき、コードが簡潔になる |
| イベントリスナー（thisを使いたい） | `function`     | `this` がイベント発生元（DOM要素）になる |
| クロージャの中で `this` を固定したい| アロー関数     | 外側の `this` を引き継げるから（例：React内の関数など） |
---
# まとめ
functionとアロー関数の違いをまとめてみました。他にも細かい違いはあるのですが本記事では割愛します。興味ある方は調べてみてください。