高階関数とコールバック関数

この記事はコールバック関数の以下の内容について解説します。

+ 高階関数とは
+ コールバック関数とは
+ コールバック関数の例
+ forEachメソッドをコールバック関数で実装してみる
+ まとめ

#高階関数
コールバック関数に入る前に、高階関数について説明します。
高階関数とは、関数を引数にとる関数の事を指します。
以下が例です。

```javascript:sample
function hello(){
 console.log('hello');
}

function hai(callback){
 callback();
}

hi(hello);
```
hi関数はhello関数を引数としているので、高階関数となります。

上の例がどのような流れなのかについて説明します。

1. hi(hello);により、hi関数が実行
2. hi関数内のcallback();より、hello関数が実行
3. hello関数内のconsole.log('hello');が実行
4. hi関数に戻るが何も処理がないのでそのまま終了

次にコールバック関数について説明します。

#コールバック関数
コールバック関数とは、高階関数に引数として渡された関数の事を指します。
上の例ですと、hello関数が該当します。

#コールバック関数の例
ここまでコールバック関数について、ざっくりとした説明をしました。
上記の内容だけでもコールバック関数が利用できるようにはなりますが、JavaScriptには関数宣言、関数式、アロー関数があるためコールバック関数も上記の書き方以外にも書き方はあります。
更にコールバック関数は引数をとることができます。関数なので当たり前なのですが、ここら辺で躓く人が多いと思います。
そこで、ここからは様々なコールバック関数の書き方を例としてあげ、コールバック関数への理解を深めていきたいと思います。

##例１ 関数宣言以外でコールバック関数をコーディング

コールバック関数は関数なので、勿論関数式でもアロー関数でも定義することができます。
以下は、高階関数を関数式で、コールバック関数をアロー関数で定義した例です。
因みに関数宣言、関数式、アロー関数が分からないという方は、<a href="https://qiita.com/KAORI04525472/items/868379074ab0642296d4">こちらへどうぞ</a>

```javascript
const func1 = function(callback) {
    console.log('例1 一番最初に実行される');
    callback();
    console.log('callbackが呼ばれた後に実行される');
};
// func1に引数として呼ばれている側なので、callback1関数はコールバック関数
const callback1 = () => {
    console.log('コールバック1');
};

func1(callback1);

```
func1(callback1)でcallback1関数を引数としたfunc1関数を実行しているので、func1関数は高階関数、callback1関数はコールバック関数となります。

この例を実行した結果は、実行結果１のようになります。

![exam1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/828037ce-4ac5-af8c-3253-22bf6c454ed9.png)
実行結果１
#例2 引数をもつコールバック関数をコーディング
コールバック関数は関数なので、勿論引数をもつことができます。
以下は、引数をもつコールバック関数の例です。

```javascript
const msg = 'コールバック２';
const func2 = function (msg, callback) {
    console.log('例2 一番最初に実行される');
    callback(msg);
    console.log('callbackが呼ばれた後に実行される');
};
const callback2 = function (message) {
    console.log(message);
};

func2(msg, callback2);
```
この例で行われている処理の流れを説明します。

1. 文字列（msg）と関数式2つ(func2, callback2)を定義しています。この時点では定義しているだけですので、実行しても何も出力されません。


2. func2(msg,callback)にて、func2関数が呼び出されています。引数は、最初に定義した文字列(msg)とコールバック関数です。

3. func2関数が呼び出されたので、func2関数内の一番最初にコーディングされたconsole.log(例2 一番最初に実行される');が実行されます。

4. 次にcallback(msg)が実行されます。callbackにはcallback2関数が代入されているので、ここでの処理はmsgを引数に持つcallback2関数が呼び出されている事になります。

5. 4.でcallback2関数が呼び出されたので、callback2関数内の一番最初にコーディングされたconsole.log(message);を実行します。

6. callback2関数内には他に処理がないので、終了となります。

7. callback(msg);が終了したので、func2関数内の次の処理にうつります。console.log('callbackが呼ばれた後に実行される');が実行されます。

8. func2関数内には他に処理がないので、終了となります。

よって、実行結果は、以下の実行結果2となります。
![exam2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/dd0848e4-f85e-88d6-7151-71df615335d5.png)
実行結果2
##例3 高階関数を呼び出すときにコールバック関数をコーディング
コールバック関数には他にもコーディングの仕方はたくさんありますが、ここでは最後に理解しにくい例をあげます。
以下、その例です。

```javascript
const msg = 'コールバック3';
const func3 = function (msg, callback) {
    console.log('一番最初に実行される');
    callback(msg);
    console.log('callbackが呼ばれた後に実行される');
};

func3(msg, (message) => {
    console.log(message);
});
```
func3関数は高階関数です。コールバック関数はどこへいったかといいますと、
(message) => {
    console.log(message);
}
がコールバック関数となっています。
例２を省略してコーディングしたものですね。省略しただけで処理の流れは同じです。
そのため、実行結果は以下の実行結果3です。
![exam3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/c8ade024-2981-9e9a-0a78-193767fa1d6a.png)
実行結果3
#forEachメソッドをコールバック関数で実装
JavaScriptにはforEachメソッドがあります。
forEachメソッドは配列の中の要素を一つ一つ実行します。これと同じことをするものをコールバック関数で実装していきます。
forEachについて知らない、もっと詳しく知りたいという方は、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">こちらへどうぞ。<a/>


```javascript
const array = ['コールバック関数', 'で', 'forEachメソッドを', '作ってみる'];

const forEach = function (array, callback) {
    for (let i = 0; i < array.length; i++) {
        callback(array[i], i);
    }
};
forEach(array, function(item, index) {
    console.log(`コールバック関数の実行${index}回目`, item);
});
```

コード内容について説明します。
1. 最初にforEachメソッドで使うための配列を用意します。
2. 次に高階関数(forEach())をコーディングしています。高階関数ではforEachメソッドの配列の要素を一つ一つ実行する、というところをfor文を使うことで実装しています。for文で配列の各要素とインデックス番号を引数とした関数を呼び出しています。
3. コールバック関数(function(item, index))を実行し、処理が全て終了すると、for文に戻ります。
4. for文の中は他に何も処理がないので、for文の外へ出ます。for文後も何も処理がないので処理は終了となります。

このコードの実行結果は以下の実行結果4になります。
![forEach.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/0315f346-ee2d-02d6-99c3-644ce72f62e9.png)
実行結果4
# まとめ
今回はコールバック関数の以下の内容について説明しました。

+ 高階関数とは、関数の引数をもつ関数のこと
+ コールバック関数とは、高階関数に引数として渡される関数のこと
+ コールバック関数の例を3つ紹介
+ forEachメソッドをコールバック関数で実装