13,115 total views, 4 views today
最近、ウェブプログラミングプライマーというサイトでJavaScriptistを勉強した。
その結果、無名関数と即時関数についてはよく分かったが、クロージャはいまいちよく分からなかった。
クロージャについてよく分からないので、[JavaScript] 猿でもわかるクロージャ超入門 まとめも読んでみたところ、クロージャの書き方は分かったが、クロージャ自体の意義がやっぱりよく分からない。
これは、クロージャを使うような場面にまだ出くわしていない(もしくは使うべき場所で使えていない)ということによるものだと思う。
そこで、復習がてら『関数』について練習することにした。
目次
関数
まずは、関数を作ってみる。
関数は、『function 関数名(仮引数){処理}』という形で表され、『関数名(実引数)』で呼び出す。
なお、引数は必ずしも設定する必要はない。
ここでは、ボタンがクリックされるとアラートが表示されるaddEventListenerの第2引数に『test』という名の関数を作って設定した。
『関数テスト』ボタンをクリックするとアラートが表示される。
HTML
<form name="test" id="test"> <input type="button" value="関数テスト" /> </form>
JavaScript
var elem = document.getElementById('test'); function test(){ alert('関数テスト'); } elem.addEventListener('click', test);
無名関数
次に、無名関数を作ってみる。
無名関数は、その名の通り関数名のない関数で、『function(仮引数){処理}』という形になる。
名前がないので、当然、後から呼び出すことはできない。
そのため、変数に代入したり、何かの実引数に設定したり、というかたちで使うことになる。
ここでは、ボタンがクリックされるとアラートが表示されるaddEventListenerの第2引数に無名関数を作って設定した。
『無名関数テスト』ボタンをクリックするとアラートが表示される。
HTML
<form name="test2" id="test2"> <input type="button" value="無名関数テスト" /> </form>
JavaScript
var elem2 = document.getElementById('test2'); elem2.addEventListener('click', function(){ alert('無名関数テスト'); });
即時関数
さらに、即時関数も作ってみる。
即時関数は、『function(仮引数){処理}(実引数);』という形で表される。
これはつまり、『function(仮引数){処理}』(無名関数)+『(実引数);』ということであり、無名関数をその場で呼び出して使う(即時)形となっている。
なお、function文が冒頭に来る場合には、『(function(仮引数){処理}(実引数));』となり、即時関数全体をカッコで括る形となる。
ここでは、ボタンがクリックされると、第2引数に無名関数(アラートを表示)を設定したaddEventListenerを実行する、という即時関数(実引数に文字列『即時関数テスト』を設定)を作った。
『即時関数テスト』ボタンをクリックするとアラートが表示される。
HTML
<form name="test3" id="test3"> <input type="button" value="即時関数テスト" /> </form>
JavaScript
(function(x){ var elem3 = document.getElementById('test3'); elem3.addEventListener('click', function(){ alert(x); }); }('即時関数テスト'));
クロージャ
最後にクロージャを作ってみる。
クロージャは、言葉で表すのが難しいようであり、
クロージャは関数とその関数が作られた環境という 2 つのものが一体となった特殊なオブジェクト
引用元:Mozilla Developer Network クロージャ
や、
JavaScriptの関数は、その関数が定義されたコンテキストとは異なるコンテキスト上にある変数に格納される時、その関数自身および関数の定義時のコンテキストが一体になった「クロージャ」という特殊なオブジェクトになる。
引用元: ANALOGIC関数を理解すればクロージャは難しくない!
などと説明されている。
ここでは、呼び出されるたびにアラートを表示したのち、カウントを1増やす無名関数、を戻り値として返す『count』という名の関数をaddEventListenerの第2引数に設定したが、カウント(変数cnt)を1増やす無名関数は、呼び出された際に自身のスコープ外にある変数cntを参照しており、この振る舞いがすなわちクロージャと呼ばれている。
『クロージャテスト』ボタンをクリックするとアラートが表示され、クリック数のカウントが1増える。
HTML
<form name="test4" id="test4"> <input type="button" value="クロージャテスト" /> </form>
JavaScript
var elem = document.getElementById('test4'); function count(){ var cnt = 1; return function(){ alert('クロージャテスト クリック' + cnt + '回目'); ++cnt; }; } elem.addEventListener('click', count());
まとめ
- JavaScriptistの勉強をして無名関数と即時関数について分かった
- クロージャはよく分からなかった
- 無名関数、即時関数、クロージャの練習をした