LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-09-22

まえがき

クロージャーを実装するのになんでこんなくそめんどくさい式を書かなくては
いけないのか
僕は式を暗記することを頑張りましたが、如何せん面白くないので、色々な実験をして
頑張って覚えることにしました

クロージャについて

クロージャーの目的

1.プライベートなスコープ
2.動的な関数
→つまり、変数の中身を確保しつつ、かつ関数を呼び出すだけで中身を追加したい時

覚えておくべきこと

1.クロージャーによって変数の中身は保持できる
2.関数自体をreturnすると関数の式自体が返ってくる
3.変更後の値を保持する必要がある

一般的な書き方

function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}

const increment = incrementFactory();
increment();
increment();
increment();

実験

実験1 直接中の変数を呼び出せばいいじゃないか?

function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
increment() 

結果、、外からは関数の中にある入れ子の関数はアクセスできない
スクリーンショット 2022-09-22 16.21.02.png

実験2 incrementFactory()を呼び出せばいいじゃないか?

function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
incrementFactory()

スクリーンショット 2022-09-22 16.24.52.png
→何も出てこない、、
理由
→return 関数と書いてある=関数の呼び出しが式そのものになる、(式はあるけど呼び出してない)
→外側の式の中で特に処理はない。
よって、、なにも出てこない

実験3 実験2で関数式が返却されたけれども、それって()をもう一個つければもしかして実行できる、、?

function incrementFactory(){
    let num = 0;
    function increment(){
        num = num + 1;
        console.log(num)
    }
    return increment;
}
incrementFactory()()

スクリーンショット 2022-09-22 16.36.55.png
→できた!!!!びっくりした
関数式()と同じなんだね!!!

実験4 実験3の結果から、ということはincrementFactory()()をくりかしたらどうなるのかな

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
理由
→毎回呼び出しても、親関数のincrementFactory()()が一旦終了してしまう
よって、、値が保持されない

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

実験5 式を変数に代入したら中の値を保持できるんじゃないか?

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()して、なんかいも呼び出してみよう

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
結果
→incrementFactory()を変数に格納する段階で、呼ばれているんだ!

実験7 親関数のincrementFactory内のnum変数はどうなっているのかな?

親関数のnumをconsole.log()して、何回も呼び出してみよう

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 関数式を格納しておくと値は保持されるのか

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をする意味
*子関数そのもののを保持する
*外部から呼び出すことができるようにする

じぶんではこう咀嚼しました。
何より一番大事なのは

人によって疑問に思う部分、前提条件が違うから、とにかく実験して、納得すること。これがすごく大事だと思いました。

長くてすみません、、

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0