【自分なりの解釈】クロージャーを理解する

# まえがき
クロージャーを実装するのになんでこんなくそめんどくさい式を書かなくては
いけないのか
僕は式を暗記することを頑張りましたが、如何せん面白くないので、色々な実験をして
頑張って覚えることにしました
# クロージャについて
## クロージャーの目的
1.プライベートなスコープ
2.動的な関数
→つまり、変数の中身を確保しつつ、かつ関数を呼び出すだけで中身を追加したい時
## 覚えておくべきこと
1.クロージャーによって変数の中身は保持できる
2.関数自体をreturnすると関数の式自体が返ってくる
3.変更後の値を保持する必要がある
## 一般的な書き方
```javascript
function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}

const increment = incrementFactory();
increment();
increment();
increment();
```
## 実験
### 実験1　直接中の変数を呼び出せばいいじゃないか？ 
```js
function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
increment() 
```
結果、、外からは関数の中にある入れ子の関数はアクセスできない
![スクリーンショット 2022-09-22 16.21.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/6a20ec32-5455-c278-12b8-6ae031d188f8.png)

### 実験2　incrementFactory()を呼び出せばいいじゃないか？ 
```js
function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
incrementFactory()
```

![スクリーンショット 2022-09-22 16.24.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/c34a23a3-4aa7-4792-816e-94d7cfd391db.png)
→何も出てこない、、
理由
→return 関数と書いてある＝関数の呼び出しが式そのものになる、（式はあるけど呼び出してない）
→外側の式の中で特に処理はない。
よって、、なにも出てこない

### 実験3　実験2で関数式が返却されたけれども、それって()をもう一個つければもしかして実行できる、、？
```js
function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
incrementFactory()()
```
![スクリーンショット 2022-09-22 16.36.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/377795fc-4044-a103-9b4d-9d05ceba8df9.png)
→できた！！！！びっくりした
関数式()と同じなんだね！！！
### 実験4　実験3の結果から、ということはincrementFactory()()をくりかしたらどうなるのかな
```js
function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
incrementFactory()()
incrementFactory()()
incrementFactory()()
```
→結果は、、
![スクリーンショット 2022-09-22 16.41.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/1229a07a-febd-0132-9290-788c29ec0539.png)
理由
→毎回呼び出しても、親関数のincrementFactory()()が一旦終了してしまう
よって、、値が保持されない

→値が保持されないので、値が保持される方法を考えよう

### 実験5　式を変数に代入したら中の値を保持できるんじゃないか？
```javascript
function incrementFactory(){
    let num = 0;
    // console.log(num)
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
const incri = incrementFactory()
console.log(incri)
incri()
```
結果
→式を呼ぶことによって式は呼び出せている。

### 実験6 親関数のincrementFactoryを、変数incriに格納した段階で、incrimentFacrory内のnum変数はどうなっているのかな？
親関数のnumをconsole.log()して、なんかいも呼び出してみよう
```js
function incrementFactory(){
    let num = 0;
    console.log(num)
    function increment(){
        num = num + 1;
        // console.log(num)
    }
    return increment;
}
const incri = incrementFactory()
```
![スクリーンショット 2022-09-22 17.01.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/5f200d2c-da07-f563-3b75-3dfb04291155.png)
結果
→incrementFactory()を変数に格納する段階で、呼ばれているんだ！
### 実験7 親関数のincrementFactory内のnum変数はどうなっているのかな？
親関数のnumをconsole.log()して、何回も呼び出してみよう
```js
function incrementFactory(){
    let num = 0;
    console.log(num)
    function increment(){
        num = num + 1;
        // console.log(num)
    }
    return increment;
}
const incri = incrementFactory()
incri()
incri()
incri()
```
実験6と結果が変わらないので、関数を格納している段階で一度しか呼ばれてないんですね。

### 実験8 関数式を格納しておくと値は保持されるのか
```javascript
function incrementFactory(){
    let num = 0;
    
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
const incri = incrementFactory()
incri()
incri()
incri()
```
# 自分なり考察の結果
1.外の関数は、スコープを確保するために存在、変数を格納する時だけに呼ばれ、num = num + 1;にnum = 0を初期化してあげたら用済み
2.returnで関数を返却しているのが、グローバルスコープから関数を呼び出せるようにすること.
3.あとは関数式を変数に格納すると、変数の評価（num+1の結果）は次に呼び出した時に引き継げるようだ

つまり
1.変数に関数式を渡す意味
*親関数の変数を一瞬使えるようにする
*子関数そのもののを保持する
*外部から呼び出すことができるようにする
2.returnをする意味
*子関数そのもののを保持する
*外部から呼び出すことができるようにする

じぶんではこう咀嚼しました。
何より一番大事なのは
#### 人によって疑問に思う部分、前提条件が違うから、とにかく実験して、納得すること。これがすごく大事だと思いました。

長くてすみません、、