[JavaScript] コールバック関数とは

# まとめ
>コールバック関数は他の関数に引数として渡される関数で、外側の関数で何らかの処理やアクションを実行します。

※mdn web docsより

# 目次
- [JavaScriptは関数も値](#JavaScriptは関数も値)
- [関数の呼び出し方と渡した方](#関数の呼び出し方と渡した方)
- [引数で関数を定義する](#引数で関数を定義する)
- [関数の引数](#関数の引数)
- [非同期処理（setTimeout関数）](#非同期処理（setTimeout関数）)

# JavaScriptでは関数も値
「関数を定数に代入できる=**関数は値の一種として扱うことができる**」
JavaScriptにおける関数は、文字列や数値、配列、オブジェクトと言った値と同じように値として扱える。
つまり、定数（文字列や数値、配列、オブジェクトと言った値）が引数として関数に渡されるように、関数もまた引数として渡される。

# 関数の渡し方と呼び出し方

下記の基本構文にて解説する。

~~~index.js
//関数introduceを定義（渡す側）
const introduce = () => {
    console.log('I am XX');
};

//関数sayHiを定義（呼び出す側）
const sayHi = (callback) => {
    console.log('Hi!');
    callback();
};

//introduceをコールバック関数としてsayHiに渡す
sayHi(introduce);

//以下、出力結果
//Hi!
//I am XX
~~~

#### 解説
- `introduce`と`sayHi`が関数として定義されている
- `introduce`は引数として`sayHi`に渡されている
- 関数を渡すときは、関数名の後ろに`()`は不要
- `()`がない場合は関数の定義そのものを指す。（関数名の後ろに`()`があると関数が呼び出される。）

#### コールバック関数の流れ
1. 引数として`introduce`が渡される
1. `sayHi`が呼び出される
1. 「引数である`introduce`は`callback`に代入される
1. `sayHi`内の処理に書かれてる`callback`に代入される（コールバック関数を呼び出す際には、`()`をつける）

上記の基本構文からわかるように、JavaScriptでは関数を引数に渡すことができる。そして、この引数になっている関数のことを**コールバック関数**と呼ぶ。

# 引数で関数を定義する
前章では、既に定義してある関数をコールバック関数として渡しましたが、引数の中で関数を定義することもできます。

~~~index.js
const sayHi = (callback) => {
    console.log('Hi!');
    callback();
};

//引数の中で関数を定義
sayHi(() => {
    console.log('I am XX');
});

//以下、出力結果
//Hi!
//I am XX
~~~

#### 解説
- `introduce`に代入していた関数をそのまま`sayHi`の引数として記述する。
- このように引数の中で関数を定義することもできる

# 関数の引数
コールバック関数には、普通の関数と同様に引数を渡すことができる。

~~~index.js
//コールバック関数に引数を渡す
const sayHi = (callback) => {
    console.log('Hi!');
    callback('XX');
};


sayHi((name) => {
    console.log(`I am ${name}`);
});

//以下、出力結果
//Hi!
//I am XX
~~~

#### 解説
- 関数`sayHi`を定義してる（関数`sayHi`は、コールバック関数`callback`を引数に取る）
- 関数`sayHi`を呼び出す際に、引数で直接``(name) => {console.log(`I am ${name}`);}``と言う関数を定義しいる
この関数は、引数に`name`を取る
- この引数`name`は、関数`sayHi`を呼び出した際に実行される
- ``(name) => {console.log(`I am ${name}`);}``は`callback('XX')`の引数`('XX')` を受け取り、 `I am XX`が出力される

# 非同期処理（setTimeout関数）
setTimeout関数を用いて、非同期処理を行う。

~~~index.js
console.log('1');

setTimeout(() => {
  console.log('2')
}, 2000);

console.log('3');

//以下、出力結果
//1
//3
//2
~~~

#### 解説
1. 上記のコードでは、`console.log('1')` → `setTimeout()` → `console.log('3')`の順番に処理が登録される **（同期処理と同じ順序）**
1. setTime関数で登録したコールバック関数(`() => {
  console.log('2')
}, 2000`)は、2000ミリ秒後に処理を実行させるように、非同期的なタイミングで呼び出される
1. `setTimeout()`よりも後に書かれているconsole.log('3')が先に実行される

# 参考リンク
- [Callback function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)
- [【JavaScriptの応用】非同期処理とコールバック関数](https://tcd-theme.com/2021/09/javascript-asynchronousprocess.html#:~:text=%E9%9D%9E%E5%90%8C%E6%9C%9F%E5%87%A6%E7%90%86%E3%81%AB%E3%81%AF%E3%80%8C%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0%E3%80%8D%E3%80%8CPromise%E3%80%8D%E3%80%8CAsync%2FAwait%E3%80%8D%E3%81%AA%E3%81%A9%E3%80%81%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E6%96%B9%E6%B3%95%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8C%E3%80%81%E3%81%93%E3%81%93%E3%81%A7%E3%81%AF%E3%80%81%E9%9D%9E%E5%90%8C%E6%9C%9F%E5%87%A6%E7%90%86%E3%81%AE%E3%82%82%E3%81%A3%E3%81%A8%E3%82%82%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%89%8B%E6%B3%95%E3%81%A7%E3%81%82%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E5%8F%96%E3%82%8A%E4%B8%8A%E3%81%92%E3%81%BE%E3%81%99%E3%80%82%20%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0%E3%81%A8%E3%81%AF%E3%80%81%E3%81%82%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%A8%E3%81%97%E3%81%A6%E6%B8%A1%E3%81%95%E3%82%8C%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%AE%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82%20%E3%81%82%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%8C%E4%B8%80%E5%AE%9A%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E7%B5%82%E3%81%88%E3%81%9F%E3%82%89%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%95%E3%82%8C%E3%82%8B%E3%81%9F%E3%82%81%E3%80%81%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0%E3%81%A8%E5%91%BC%E3%81%B0%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82%20setTimeout%E9%96%A2%E6%95%B0%20JavaScript%E3%81%AE%E4%BB%A3%E8%A1%A8%E7%9A%84%E3%81%AA%E9%9D%9E%E5%90%8C%E6%9C%9F%E5%87%A6%E7%90%86%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0%E3%81%A8%E3%81%97%E3%81%A6%E3%80%81%20setTimeout%20%E9%96%A2%E6%95%B0%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82,console.log%28%271%27%29%3B%20setTimeout%28%28%29%20%3D%3E%20%7B%20console.log%28%272%27%29%20%7D%2C%201000%29%3B)