まえがき
クロージャーを実装するのになんでこんなくそめんどくさい式を書かなくては
いけないのか
僕は式を暗記することを頑張りましたが、如何せん面白くないので、色々な実験をして
頑張って覚えることにしました
クロージャについて
クロージャーの目的
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()
結果、、外からは関数の中にある入れ子の関数はアクセスできない
実験2 incrementFactory()を呼び出せばいいじゃないか?
function incrementFactory(){
let num = 0;
function increment(){
num = num + 1;
console.log(num)
}
return increment;
}
incrementFactory()
→何も出てこない、、
理由
→return 関数と書いてある=関数の呼び出しが式そのものになる、(式はあるけど呼び出してない)
→外側の式の中で特に処理はない。
よって、、なにも出てこない
実験3 実験2で関数式が返却されたけれども、それって()をもう一個つければもしかして実行できる、、?
function incrementFactory(){
let num = 0;
function increment(){
num = num + 1;
console.log(num)
}
return increment;
}
incrementFactory()()
→できた!!!!びっくりした
関数式()と同じなんだね!!!
実験4 実験3の結果から、ということはincrementFactory()()をくりかしたらどうなるのかな
function incrementFactory(){
let num = 0;
function increment(){
num = num + 1;
console.log(num)
}
return increment;
}
incrementFactory()()
incrementFactory()()
incrementFactory()()
→結果は、、
理由
→毎回呼び出しても、親関数の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()
結果
→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をする意味
*子関数そのもののを保持する
*外部から呼び出すことができるようにする
じぶんではこう咀嚼しました。
何より一番大事なのは
人によって疑問に思う部分、前提条件が違うから、とにかく実験して、納得すること。これがすごく大事だと思いました。
長くてすみません、、