【JavaScript】forEach,  map,  filter の前に、アロー関数とコールバック関数を押さえよう

## はじめに

配列のメソッドである`forEach`, `map`, `filter`がよくわからない！っていう人は、もしかしたらアロー関数とコールバック関数の理解があやふやなのかもしれません（私はそうでした。。）

この記事では、まず従来の関数の書き方を復習してから、アロー関数とコールバック関数について説明します。

その後、`forEach`, `map`, `filter`について説明していきます。

## 従来の関数の復習

まず、（アロー関数でない）従来の関数の書き方を復習しておきます。

### 関数宣言

関数はこのように宣言します。

```javascript
function fn() {
    // 関数が呼び出された時の処理
}
```

### 関数式

数値や文字列等と同じように、**関数自体も変数に代入できます**。
関数を変数に代入している式を**関数式**と言います。

```javascript
const fn = function() {
    // 関数が呼び出された時の処理
}
```

この変数に代入された関数式は名前を持たない[^1]ため、**無名関数**と呼ばれます。

## アロー関数

アロー関数はES2015から導入された関数式の記述方法です。
名前の通り矢印 `=>` を使って無名関数を定義します。

```javascript
const arrowFn = () => {
    // 関数が呼び出された時の処理
}
```

`()`で引数を受け取り、`{}`内で処理を行います。

具体例を見ていきましょう。

```javascript
const doubleFn = (num) => {
    return num * 2;
}

console.log(doubleFn(1)); // 2
```

引数を`num`で受け取り、`num * 2`を実行して結果を返しています。

### 省略記法

アロー関数は、条件を満たせば省略して書くことができます。

| 条件                          | 省略できるところ                                       | 
| ----------------------------- | ------------------------------------------------------ | 
| 引数が1つ                     | `()`は省略可                                           | 
| `{}`内で処理される関数式が1つ | `{}`と`return`が省略可（関数式の結果が返り値になる） | 

上の例のアロー関数は条件を両方とも満たすので、以下のように省略して書けます。

```javascript
const doubleFn = num => num * 2;
```

## コールバック関数

コールバック関数は、**引数として関数に渡される関数**のことです。

コールバック関数はES2015から導入されたわけではなく、従来の関数でも使用できます。

### 従来の関数

```javascript
function sayHello() {
  console.log("Hello");
}

function greet(callback) {
    callback(); // "Hello"
}

greet(sayHello); 
```

`sayHello`関数がコールバック関数です。`greet`関数の引数として渡されています。

そして、`sayHello`関数は、`callback()`として実行され、`Hello`が表示されてます。

### 無名関数

コールバック関数に名前をつけず、**無名関数を引数として直接渡す**こともできます。

```javascript
// sayHello関数を作らない

function greet(callback) {
    callback();
}

greet(function() {
  console.log("Hello");
})
```

`sayHello`関数は作らず、直接`greet`関数に無名関数を渡しています。

### アロー関数

そして、コールバック関数をアロー関数で書くと以下のようになります。

```javascript
greet(() => {
  console.log("Hello");
})
```

ここまで理解できれば、`forEach`メソッドなども理解しやすくなると思います。

## forEach

さて、いよいよ本題の`forEach`メソッドの説明に入りましょう。

`forEach`は、**配列の要素1つ1つに対して、与えられたコールバック関数を実行する**メソッドです。

```javascript
const numbers = [1, 2, 3];
numbers.forEach((num) => {
  console.log(num); // 1 2 3
});
```

配列`numbers`の要素が順番にコールバック関数の引数`num`に渡され、`console.log(num);`が実行されます。

| numbersの要素 | num | 実行される関数式 | 
| ---------- | --- | ---------------- | 
| 0番目          | 1   | console.log(1);  | 
| 1番目          | 2   | console.log(2);  | 
| 2番目          | 3   | console.log(3);  | 

### 省略記法

条件を満たしていればコールバック関数を省略して書けます。

```javascript
numbers.forEach(num => console.log(num));
```

## map

`map`メソッドは、**配列の要素1つ1つに対して、与えられたコールバック関数を実行し、実行結果を新しい配列として返します**。

```javascript
const numbers = [1, 2, 3];

const newNumbers = numbers.map((num) => {
  return num * 2;
});

console.log(newNumbers); // (3) [2, 4, 6]
```

配列`numbers`の要素が順番にコールバック関数の引数`num`に渡され、`num * 2`を実行します。

`forEach`と異なるのは、**実行結果を新しい配列として返す点**です。

返ってきた配列を`newNumbers`という変数に格納しています。

### 省略記法

条件を満たしていればコールバック関数を省略して書けます。

```javascript
const newNumbers = numbers.map(num => num * 2);
```

## filter

`filter`メソッドは、**配列の要素1つ1つに対して、与えられたコールバック関数を実行し、条件を満たす要素だけを新しい配列として返します**。

```javascript
const evenNumbers = numbers.filter((num) => {
  return num % 2 === 0;
});

console.log(evenNumbers); // (2) [2, 4]
```

配列`numbers`の要素が順番にコールバック関数の引数`num`に渡され、`num % 2 === 0`を実行します。

`map`と異なるのは、**実行結果がtrueの場合だけ新しい配列として返す点**です。

返ってきた配列を`evenNumbers`という変数に格納しています。

### 省略記法

条件を満たしていればコールバック関数を省略して書けます。

```javascript
const evenNumbers = numbers.filter(num => num % 2 === 0);
```

## おまけ ： reduceメソッドについて

同じく配列のメソッドである`reduce`については別途記事にまとめましたので、以下をご参照ください。

https://qiita.com/wsigma21/items/dccb73a6b088a27193c0

[^1]:fnは**変数**の名前であり、代入された関数式自体には名前がついていません

## 参考資料

- [JavaScript Primer](https://jsprimer.net/)
- [MDN](https://developer.mozilla.org/ja/)