4歳娘「パパ、そんなときはクロージャが役に立つんじゃない？」

↓新しい記事もよろしくやで！

+ [**4歳娘「パパ、懐かしいJavaScript書いてるね！」**](https://qiita.com/Yametaro/items/70e7878c5ea51788b643)
+ [**4歳娘「パパ、constしか使わないで？」**](https://qiita.com/Yametaro/items/17f5a0434afa9b88c3b1)

## 休日ワイ
ワイ「（カタカタカタカタ・・・・・・）」

娘（**4歳**）「パパ、お休みの日までお仕事してるの？」

ワイ「ん？これはお仕事とちゃうで」
ワイ「ワイの**オリジナルポエム**を販売するための」
ワイ「**ポエム販売サイト**を作ってんねん」

娘「**Qiita**に書き溜めた**ポエム**を、とうとう有料で販売するんだね！」

ワイ「**誰の記事がポエムやねん**」
ワイ「これは**れっきとした技術記事**や」

娘「そっか」

ワイ「そうやなくてな」
ワイ「ワイが作った、心温まるポエムを販売して」
ワイ「それで生計を立てて」
ワイ「働かんでええようにするんや！」

娘「パパ、すごい！」

ワイ「ぐへへ」
ワイ「まあ、下手に仕事を辞めたりしたら」
ワイ「**路頭に迷ってしまう**かもしれんから」
ワイ「ちょっと不安やけどな・・・」

娘「パパならきっと大丈夫だよ！」

ワイ「ありがとうな、娘ちゃん」
ワイ「よっしゃ、今日もガンガン開発していくで！」

## 今から開発する機能

ワイ「今日は、**ボーナスポイント機能**を作るんや！」

娘「**ボーナスポイント機能**？」

ワイ「せや」
ワイ「この**ポエム販売サイト**で**会員登録**をしてくれたお客様は」
ワイ「ポエムを購入するたびに**ポイント**をゲットできるんや」
ワイ「そのポイントを溜めて、またポエムを買うことができるんや」

娘「**画期的なシステム**だね！」

ワイ「せや」
ワイ「発明やでこれは」
ワイ「しかもやな」
ワイ「毎月10日にサイトを訪れたお客様は」
ワイ「**ボーナスポイント**として**3ポイント**がもらえるんや」

娘「すごーい」

ワイ「1ポエムが**360円**やから・・・」

娘「**たった10年**で1ポエムもらえちゃう感じだね！」

ワイ「せやな！」
ワイ「でもな・・・」
ワイ「今その**ボーナスポイント機能**のことで行き詰まってんねん」

娘「どんな風に行き詰まってるの？」

ワイ「ええとな」
ワイ「画面上に、**ボーナスポイントをGET！**って書いてある**ボタン**があるやろ？」

娘「うん」

ワイ「このボタンをクリックすると」
ワイ「**JavaScript**で`getBonusPoint`っていう関数が実行されて」
ワイ「それによって会員さんのポイントが増える仕組みなんやけど」

娘「うんうん」

ワイ「現状、何回もクリックすると**無限に**ボーナスポイントがもらえてしまうんや」

娘「そっか・・・」
娘「ちょっと**お客様ファースト過ぎる**ね」

ワイ「そうなんよ・・・」

## 1回だけ`getBonusPoint`したい

ワイ「要は、`getBonusPoint`は**1回しか実行できない**・・・」
ワイ「そんな感じにしたいんや」

娘「じゃあ・・・」
娘「こんな感じにすればいいんじゃない？」

```javascript:JavaScript
// ボーナス取得済みかどうかのフラグ
let flag = false;

const getBonusPoint = (member) => {
    if (flag) {
        alert("アカン！");
    } else {
        member.point += 3;
        flag = true
    }
};
```
ワイ「なるほどな」
ワイ「ええと・・・？」

## 娘ちゃんのコードを読んでみる
ワイ「まずは・・・」

```javascript:JavaScript
// ボーナス取得済みかどうかのフラグ
let flag = false;
```

ワイ「↑ここで**ボーナス取得済みかどうかのフラグ**を定義してるんやね」
ワイ「初期値は`false`か」
ワイ「ほんで・・・」

```javascript:JavaScript
const getBonusPoint = (member) => {
    if (flag) {
        alert("アカン！");
    } else {
        member.point += 3; // ポイント付与
        flag = true
    }
};
```

ワイ「↑これが`getBonusPoint`関数やな」
ワイ「`flag`が`true`の場合は」
ワイ「既にボーナスポイント**取得済み**ってことやから」
ワイ「`"アカン！"`ってアラートを出すんやな」

娘「そうそう」

ワイ「逆に`flag`が`false`の場合は」
ワイ「会員さんのポイントを`3`増やしてあげて」
ワイ「そのあと`flag`を`true`にする」
ワイ「つまり、フラグを**ボーナスポイント取得済み状態**に変更するってことか」
ワイ「なるほど・・・」
ワイ「こうなってれば、1回しか`getBonusPoint`は実行されへん訳やな」

## 試してみる

ワイ「一応試してみよか」

```javascript:JavaScript
// たかし君という会員は0ポイントを持っている。
const member = {
    name: "たかし",
    point: 0
}

// getBonusPointを2回実行。
getBonusPoint(member);
getBonusPoint(member);

// そのあと、たかし君のポイントを確認してみる。
console.log(member.point);
```

ワイ「おお、ちゃんと`"アカン！"`ってアラートが表示されたし」
ワイ「たかし君のポイントも`3`や」
ワイ「1回しか増えてへんわ」
ワイ「大丈夫そうやな」

## でも、なんか不安
ワイ「でも・・・」
ワイ「コードのどこかで間違って」

```javascript:JavaScript
flag = false;
```

ワイ「↑みたいなコードを、もしも書いてしまったら・・・」
ワイ「また**ボーナスポイント**を取得できてしまうわけか・・・」
ワイ「なんか、一抹の不安が残るな・・・」
ワイ「`flag`が、**丸出しのグローバル変数**なのが怖いわ・・・」
ワイ「`flag`はもっと、**自由に触れない変数**であってほしいわ・・・」

娘「**パパ、そんなときはクロージャが役に立つんじゃない？**」

ワイ「クロージャ・・・」
ワイ「・・・将来のワイのことか？」

娘「それは**浮浪者**でしょ！」

ワイ「おお、せやった」

よめ太郎「（**けっきょく路頭に迷う想定なんかい**）」

娘「そうじゃなくて、私が言ってるのは**クロージャ！**」

## クロージャって何やっけ
娘「クロージャっていうのは」
娘「**関数**と、**その関数が宣言された環境**の**組み合わせ**だよ」

ワイ「ふーん」
ワイ「全く分からんけど、その**『関数と環境の組み合わせ』**のことをクロージャって呼ぶんや？」

娘「そう」
娘「言い換えると、**環境を持ってる関数**だね」

ワイ「環境を持ってる・・・？」

娘「そう」

ワイ「よう分からんから・・・」
ワイ「コードを書きながら説明してもらえる・・・？」

娘「そうだね」
娘「まずは、さっきの`getBonusPoint`を**作るための関数**を書くの」

ワイ「**関数を作るための関数**・・・？」

娘「そう」
娘「書いていくね」

```javascript:JavaScript
const makeFunction = () => {

};
```

娘「↑**関数を作るための関数**だから」
娘「名前はとりあえず`makeFunction`にしておくね」

ワイ「ほうほう」

娘「で、その`makeFunction`の中に」
娘「さっきの`flag`っていうフラグと」
娘「`getBonusPoint`関数を入れちゃうの」

```javascript:JavaScript
const makeFunction = () => {
    let flag = false;
    const getBonusPoint = (member) => {
        if (flag) {
            alert("アカン！");
        } else {
            member.point += 3;
            flag = true
        }
    };
};
```

ワイ「おお、全部入れてまうんや」

娘「そう」
娘「でも、これだけだと`flag`も`getBonusPoint`も」
娘「ローカルスコープの中に**閉じ込められて**」
娘「どこからもアクセスできなくなっちゃうから」
娘「`makeFunction`関数の最後の部分で」
娘「**戻り値**として`getBonusPoint`関数を返してあげるの」

```javascript:JavaScript
const makeFunction = () => {
    let flag = false;
    const getBonusPoint = (member) => {
        if (flag) {
            alert("アカン！");
        } else {
            member.point += 3;
            flag = true
        }
    };
    return getBonusPoint; // <- 関数を返す。
};
```

ワイ「ほうほう」
ワイ「要は`makeFunction`関数は」
ワイ「`getBonusPoint`関数を作って、返してくれる関数やね」

娘「そう」
娘「こうすることで、変数`flag`が」
娘「関数の中の変数・・・つまり**ローカル変数**になるでしょ？」

ワイ「おお、せやな」
ワイ「ローカル変数やから、**関数の外からはアクセスできんくなる**わけか・・・！」

娘「そうそう」
娘「その次はね・・・」

```javascript:JavaScript
const func = makeFunction();
```

娘「↑こんな風に、`makeFunction`で作った関数を受け取るの」

ワイ「ほうほう」

娘「どうせなら、同じ`getBonusPoint`っていう名前で受け取るね」

```javascript:JavaScript
const getBonusPoint = makeFunction();
```

ワイ「おお、`func`やと**アレ**やしね」

娘「こうすることで」
娘「`flag`は関数の中に**閉じ込められて**」
娘「ローカル変数になったから」
娘「外部からアクセスできなくなった」

ワイ「せやな」

娘「でも、`getBonusPoint`関数からだけは」
娘「フラグを`false`に変更することができる・・・」

ワイ「おお・・・」

娘「つまり、**他の誰からも触れない**・・・」
娘「**自分だけが変えられるフラグを持った関数**ができたの」

ワイ「おお・・・！」
ワイ「さっき・・・」

> 娘「言い換えると、**環境を持ってる関数**だね」

ワイ「・・・って言うてたのは、そういうことか」
ワイ「**自分だけがアクセスできて・・・**」
ワイ「**自分だけが変えられる・・・**」
ワイ「そんな**閉じた環境**を持ってる関数やな」

娘「そう」

ワイ「なるほどなぁ」
ワイ「初めは・・・」

> 娘「クロージャっていうのは」
> 娘「**関数**と、**その関数が宣言された環境**の**組み合わせ**だよ」

ワイ「↑この**関数と環境の組み合わせ**って言葉の意味が、全く分からんかったけど」
ワイ「何となく分かってきたで・・・！」
ワイ「クロージャ、**素敵やん・・・！！！**」

娘「関数の中、つまりローカルスコープに変数と関数を**閉じ込める**ことで」
娘「**他からはアクセスできないけど、その関数からだけはアクセスできる変数**を作る」
娘「そして関数の方だけは、外からも実行できるように**戻り値**として返してやる」

ワイ「おお・・・」
ワイ「なんか、ドラえもんの**タイムマシンの穴**が閉じる前に」
ワイ「穴の中から**リモコンを投げてもらって**」
ワイ「閉じ終わったタイムマシンの**穴の中と通信できる**みたいな」
ワイ「そんな感じやね」

娘「す、すごい例えだね」
娘「まあタイムマシンは関係ない気もするけど」
娘「**穴が閉じてもリモコンが残る**みたいなイメージは近いかもね」

ワイ「せやろ！」
ワイ「・・・でも、なんで**クロージャ**っていう名前なんやろ？」

娘「うーん」
娘「変数と関数をローカルスコープに**閉じ込める**ことで形成されるものだからじゃない？」
娘「**Closure**って、**閉鎖**とか**閉塞**って意味だからね」
娘「日本語では**関数閉包**なんて言うみたいだけど」

ワイ「なるほどなぁ・・・」
ワイ「ありがとうやで、娘ちゃん！！！」



## まとめ
+ クロージャは、ローカルスコープという**閉じた環境**で作られた関数。
+ クロージャは、自分が作られたとき周囲にあった環境にアクセスすることができる。
+ クロージャは、同じローカルスコープにあった変数にアクセスできる唯一の手段になる。
+ 関数をクロージャにすることで、**その関数からのみ変えられるフラグ**を持たせることができた。
+ もっと他にも色々できそう。

ワイ「↑こんな感じやね！」

娘「そうだね」
娘「でも・・・」
娘「なんかフロントエンドだけで会員のポイントを増やしたりして」
娘「意味わかんないから、このシステム**作り直した方がいいよ**」

ワイ「・・・**いや早く言わんかい！**」

**〜おしまい〜**

## おまけ

娘「まあ、クロージャの使い方が学べたからいいじゃん」

ワイ「せやな・・・」

## 新しい記事もよろしくやで！

+ [**4歳娘「パパ、懐かしいJavaScript書いてるね！」**](https://qiita.com/Yametaro/items/70e7878c5ea51788b643)
+ [**4歳娘「パパ、constしか使わないで？」**](https://qiita.com/Yametaro/items/17f5a0434afa9b88c3b1)

## 参考文献

+ [クロージャ - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Closures)
+ [関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Functions)
+ [九章第五回 クロージャ — JavaScript初級者から中級者になろう](https://uhyohyo.net/javascript/9_5.html)