--クロージャと即時関数--
【開発環境】
OS;Window10
Webブラウザ:Google Chrome
テキストエディタ:Brackets
【クロージャ】
クロージャは、関数内で、その外側の変数を保持する仕組み。

1)もっともシンプルなクロージャ
サンプルプログラム「closure1.html」
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>JavaScriptのテスト</title>
</head>
<body>
<script>
//グローバル変数
var counter = 0;
//関数定義
function countUp(){
return ++counter;//カウントUPしてreturn文で返す
}
console.log(countUp());
console.log(countUp());
console.log(countUp());
</script>
</body>
</html>
・実行結果

2)関数を返す関数でクロージャを作成する
JavaScriptの関数はファーストクラスオブジェクトですので、関数を戻り値とすることが出来る。
・サンプルプログラム「closure2.html」
<script>
//外部関数
function createFunc() {
var str = "こんにちは";
//内部関数
function sayHello() {
console.log(str);
}
// sayHello()関数を返す
return sayHello;
}
//変数に外部関数の戻り値;sayHello()関数を代入
var myFunc = createFunc();
myFunc();クロージャ化した関数を呼び出す
</script>
・実行結果

3)変数はクロージャごとに保持される
クロージャの中に閉じ込めれた変数は、クロージャごとに個別の値を持ちます。オブジェクトのインスタンスがそれぞれ個別のプロパティを持つのと同じようなイメージ
・サンプルプログラム「closure3.html」
<script>
function createFunc(str){
//内部関数
function sayHello(){
console.log(str);
}
// sayHello()関数を返す
return sayHello;
}
var myFunc1 = createFunc("こんにちは");
myFunc1();
var myFunc2 = createFunc("さようなら");
myFunc2();
</script>
・実行結果

4)クロージャを使用してカウンタを作成する
クロージャを生成した後、クロージャ内の変数の値を変更することも出来ます。
<script>
function makeCounter(initValue) {
内部関数
function counter() {
console.log(++initValue);
}
return counter;戻り値
}
// 初期値を0にしたカウンタ
var counter1 = makeCounter(0);
呼び出し
counter1();
counter1();
counter1();
// 初期値を10にしたカウンタ
var counter2 = makeCounter(10);
呼び出し
counter2();
counter2();
counter2();
</script>
・実行結果

5)DOMの操作でクロージャが必要な例
ジャンプ先のURLを保存した変数をクロージャに閉じ込めて置くことで、正しく動作させることが出来る。
・サンプルプログラム「clump2.html」
~
<body>
<p>
<input type="button" id="search" value="検索">
<input type="button" id="weather" value="天気">
<input type="button" id="news" value="ニュース">
</p>
<script>
var links = {
"search": "http://google.co.jp",
"weather": "http://weather.yahoo.co.jp",
"news": "http://www.asahi.com"
};
// クロージャを生成→onclikイベントハンドラに登録するクロージャを返す
function makeLink(){
var loc = links[key];
//無名関数:location.hrefプロパティに変数locを代入して戻しています。これでクロージャに、リンク先のURLを管理する変数locが閉じ込められる
return function(){
location.href = loc;
};
};
var btn;
// クリックしたらリンク先にジャンプ
for (key in links) {
btn = document.getElementById(key);
btn.onclick = makeLink();←makeLink()により生成したクロージャを、onclickイベントハンドラに代入する
}
</script>
</body>
~
・実行結果

【即時関数】
即時関数は、無関数を変数に代入せずに実行するテクニックである。即時関数を利用すると、グローバル変数を気にすること無く、自由に変数を使用出来ます

・サンプルプログラム「wordOfToday1.html」
省略
<body>
<h1 id="wordOfToday"></h1>
<script>
// この部分に既存のプログラムがあってもよい
//即時関数
(function () {
//HTML要素の取得
var element = document.getElementById("wordOfToday");
//配列
var proverbs = ["弘法も筆の誤り", "濡れ手に粟",
"吠える犬は滅多に噛まぬ",
"灯台もと暗し", "転ばぬ先の杖"];
//乱数を使用して諺をランダムに取り出し、id属性が「wordOfToday」のh1エレメントに表示される
element.innerHTML = proverbs[Math.floor(Math.random() * proverbs.length)];
})();
// この部分に既存のプログラムがあってもよい
</script>
</body>
省略
・実行結果

※コメント投稿者のブログIDはブログ作成者のみに通知されます