なんか、ふとしたはずみで使えちゃったので、分かったうえで書いた(はずの)コードを3種類貼ってみます。
ひよこつつきゲームに出てくるコードです。
アハ体験のきっかけはこの動画です。途中でサラッとクロージャが出現します。
ヒット数カウンター
よく例示されているような、関数を返す関数です。
関数内で定義した変数countを、返した関数によってインクリメントしていきます。
var initHitCounter = function(){
var count = 0;
var counter = document.getElementById("hit-count");
counter.textContent = 0;
return function(){
count++;
counter.textContent = count;
return count;
};
};
var hitCount = initHitCounter();
ひよこをつついた時に、hitCount関数を呼び出すと、countが一つ増えます。
再代入するとリセットされます。
スコアカウンター
関数を返す関数の発展形。
単純なインクリメントじゃない事もできました。
scoreCalcに渡す変数の種類(=キャラクターの種類)によって、加算されるスコアが変わります。
var initScore = function(){
var score = 0;
var lastScore = 1;
var view = document.getElementById("score");
view.textContent = 0;
return function(type){
switch(type){
case "piyo":
lastScore = 1;
break;
case "food":
lastScore = lastScore * 2;
break;
//~~省略(全ての種類についてスコアを設定)
default:
return;
}
score += lastScore;
view.textContent = score;
return score;
};
};
var scoreCalc = initScore();
ヒット時動作を付与する仕組み
こちらはちょっと複雑かも。
ヒヨコを出現させる関数内で、ヒヨコにオンクリックの動作を付与する部分です。
これは完全に冒頭の動画からひらめきました。
関数内にさらにスコープ(の代わりの即時関数)を作って、変数をトラップしています。
こうすると、次のヒヨコを出現させる時に、同じ関数を呼んでも、いちどトラップした変数_idは影響を受けません。
//ヒヨコ出現メソッド
var appear = function(actor, n){
//~~省略(出現座標を決める)
//表示する要素を作る
var piyo = document.createElement('div');
piyo.id = n;
//~~省略(piyoのstyleを設定)
(function(){
var _id = n;
piyo.onclick = function(){hitfunction(_id);};
})();
field.appendChild(piyo);
//~~省略(出現アニメーションをセット)
};
(ここでは値そのものをトラップしてますが、参照渡しのもの(配列とか)は、たぶんトラップしても意味ないので気をつけましょう)
余談
というわけで、クロージャ3パターンでした。
ところで、仮完成してテストプレイしてると、どうもフリーズすることがあるので、コードの挙動を詳しく調べてみました。
クロージャの使い方が悪いと、循環参照やらメモリリークやら起きるらしいんですが、スクリプト自体は循環参照には陥っていないようでした。
そうではなく、ひよこを無限に生成していることで、クラッシュしてた模様。(上記のひよこ出現メソッド)
DOM上から要素を剥がせば、勝手に破棄されると思ってましたが、そうでもないらしい。(←良く分かってない)
このへんクロージャのせいなのか、他の要因か分かりませんが、とりあえず生成するDOM要素を有限個に制限したら、固まらなくなったようです。
ふう。
あとがき
クロージャって自転車に乗るようなもので、説明文を読んでも分かるような分からんような感じです。
使えるようになって初めて「そうか!」ってなります。
と、どっかのサイトに書いてあったんですが、まさにその通りでした。
面白い、けどまだまだ奥が深い・・・!
そんなとこでした。
コメント