(function(){ ... })() の個人的な解釈
- (function(var){..............})(var) と function(var){............} の違い。つまり、クロージャ。 - それ図解で。・・・tohokuaikiのチラシの裏
- via: (function(){})() と function(){}() - IT戦記
解釈としてはオブジェクトの後ろに()
をつけると関数とみなされて実行されるにつきると思う。
実際、どう見ても関数でないものでも後ろに()
をつけると関数として評価しようとがんばってくれる。
var hoge = new Object(); hoge() TypeError on line 1: hoge is not a function 10() TypeError on line 1: 10 is not a function true() TypeError on line 1: true is not a function 'hogehoge'() TypeError on line 1: "hogehoge" is not a function
ということは、functionオブジェクトに()
をくっ付ければ実行されるんじゃないか、ってのが(function(){ ... })()
の考え方だろう。
(function(){ ... })
での()
はよく使う演算を優先させる(?)()
で、一つのグループとして評価させる意味があり、括らないと別々に評価されてしまい結果的にfunctionオブジェクトとみなしてくれないのではないかと個人的には思っていた。
が、きちんとした意味では
function() {} が式ではなく、文として解釈されてしまうからだ。
(function(){})() と function(){}() - IT戦記
ということらしく、文と式の違いいみたいだ。
document.observe('dom:loaded', function() { $('selection').observe('click', (function() { var SELECTED_CLASS_NAME = 'selected'; var selected; return function(event) { if(selected) selected.removeClassName(SELECTED_CLASS_NAME); event.target.addClassName(SELECTED_CLASS_NAME); selected = event.target; }; })()); });Young risk taker.: クロージャを利用したイベントリスナの登録
だけど、これは宣言するといきなり
(function() { var SELECTED_CLASS_NAME = 'selected'; var selected; return function(event) { if(selected) selected.removeClassName(SELECTED_CLASS_NAME); event.target.addClassName(SELECTED_CLASS_NAME); selected = event.target; }; })());
が実行される。関数を実行すればリターン値が返る。この場合はfunctionオブジェクトだ。そして、スコープの概念として親を参照する事はできるけれど、子や兄弟はできない。よってSELECTED_CLASS_NAME,selected変数はリターン値である関数のみが参照でき、さらに親の(function(){ ... })()
は一回実行されるのみなので新たに初期化されることもない。
そして、返されたfunctionオブジェクトは$('selection').observe
メソッドの引数となる。リターン値として返された後も関数は宣言された時のスコープを保持しているので依然SELECTED_CLASS_NAME,selected変数を参照できる。
ここら辺の説明はJavaScript 第5版のCollオブジェクト辺りを読んだ方が良いかもしれない。
そういえば、Young risk taker.: クロージャを利用したイベントリスナの登録の例はprototype.jsを使っていることが前提のようだが、その前提が分からないとさっぱりなコードだね(ソースまで読んでやっと理解できた)。