JavaScriptにおける関数の実行の流れを知りたい！！

はじめまして！！ノベルワークス入社2年目のそうまです！！！

今回は `javascript` で中々見えづらいデータの動きを関数に着目して調査したので、ノートとして残そうと思います！！

## 調査のきっかけ
直近でデータ移行の業務に携わる機会がありました。この業務では、大量のデータを効率よく処理するために、メモリを意識したコードを書く必要がありました。しかし、普段は `JavaScript` しか触っておらず、メモリを意識する機会が無いため「メモリ割当って何？？」という基本的な状態から学び直す必要がありました。

<details><summary>何故メモリを意識しなくて良いか</summary>

`javascript` 等の高級言語はほぼ一様に[ガベージコレクション](https://developer.mozilla.org/ja/docs/Glossary/Garbage_collection)を搭載しており、メモリの割り当て・解放を自動的に行ってくれるため。

</details>

そのとき、「JavaScript Visualizer 9000」というWebサービスに出会いました。このツールは、関数がスタックやキューにどのように出し入れされているかを視覚的に確認できるものです。「まずはこれを使えば、関数のメモリ割り当てや解放の流れを掴むための参考になるかも！」と思い、早速試してみることにしました！

![スクリーンショット 2025-01-07 21.16.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/531a3b03-b21b-470d-fed9-7de234dba5d8.png)

https://www.jsv9000.app/

### 

## 関数実行の流れ
早速ですが以下のようなコードがあったとします、関数がどの順番で[コールスタック](https://developer.mozilla.org/ja/docs/Glossary/Call_stack)に追加され、その後削除されるかを考えてみましょう。 `javascript` の[コードの実行順](https://developer.mozilla.org/ja/docs/Learn_web_development/Core/Scripting/What_is_JavaScript#javascript_%E3%81%AE%E5%AE%9F%E8%A1%8C%E9%A0%86%E5%BA%8F)基づいて考えると理解しやすいかもしれません！

:::note info
コールスタック
どの関数が現在実行されていて、その関数の中でどの関数が呼び出されたかを追跡するための仕組み。
:::

```js
function a(){}

function b(){}

function c(){}

a()

b()

c()

```
このコードでは、以下の順番で関数がコールスタックに追加され、削除されます！

![頭整理.drawio (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/610e2310-f7bc-9558-19d5-ce0a6a926584.png)

1. `a` 関数がコールスタックに追加 → 実行後に削除
2. `b` 関数がコールスタックに追加 → 実行後に削除
3. `c` 関数がコールスタックに追加 → 実行後に削除


では、次の例ではどうなるでしょうか？

```js
function a(){}

function b(){ a() }

function c(){ b() }

c()
```
この場合は以下のようになります！

![頭整理.drawio (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/cf5599c5-6b8d-cc01-4aef-4d8b7ee8df2d.png)

この場合、関数がネストして呼び出されるため、以下のようにコールスタックが変化します!

1. `c` 関数がコールスタックに追加 → `b` 関数を呼び出す
2. `b` 関数がコールスタックに追加 → `a` 関数を呼び出す
3. `a` 関数がコールスタックに追加 → 実行後に削除
4. `b` 関数を削除 → 最後に `c` 関数を削除

https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF

### `setTimeout`関数 と タスクキュー
この2つの関数は特殊で、指定したミリ秒後にコールバック関数の実行します、では以下のようなコードがあったとして"指定したミリ秒" の間どのように実行を待つのでしょうか？
```js

setTimeout(function a(){}, 1000)

```

正解は「タスクキュー」に格納され、実行を待つ事になります！

:::note info
キュー
javasctiptにおけるキューは、処理に紐づいているメッセージをリストとして持っており、必要な時キューからメッセージが取り出され実行される仕組みになっている。
:::

![頭整理.drawio (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/cdb83b31-24a5-28a3-7271-5a5b4097afd4.png)

タスクキュー内では、メインスレッドの処理が完了した後にコールバック関数が実行されます！

https://developer.mozilla.org/ja/docs/Web/JavaScript/Event_loop


### `then` と `catch`
`then`や`catch`といった関数は、`Promise`の状態が`pending`から解消（fulfilledまたはrejected）された後に実行されます。この際、`setTimeout`関数と同様に待ち時間が発生しますが、格納されるキューが異なり、これを「マイクロタスクキュー」と呼びます。

こちら`Promise`に関しては、`Promise.resolve()`のような直ぐに結果を返す`Promise`を返す「マイクロタスク」と、`fetch`のように非同期処理の結果を待って解決される「マクロタスク」に依存するものがあります。それぞれキューに格納されるタイミングが異なり非常にややこしいのでこれに関しては別で記事にしようと思います！！

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise

## 纏め
今回は`JavaScript`における関数がいつ実行されるのか大体の流れを掴む事が出来ました！特にコールスタックやタスクキューの動作を理解することで、JavaScriptのコード実行順序をより深く理解出来たように思えます！

次回は`Promise`を返す「マイクロタスク」がどのような仕組みで動き、キューへと格納されるのかを調査したいとおもいます！！