JavaScriptのIIFEとモジュールパターン

他の多くのフラッシャーと同じく、最近色々HTML5開発を触ってみている。(現時点ではEdge Animateで色々を。)で、JSはAS3とかなり似ているため、それほど慣れにくくはない。(ほとんどのJSはAS3としてでもコンパイルできるし。JSを横目で見たら、変数の型を宣言しない人が書いたAS3と見間違えられる。)

ただしJSとAS3は似ている言語にしても、使われる方言が違う。例えばこれ:

(function foo(n) {
// 処理…
})(5);

最初は「はあ?」と思った。でもJSにはよ〜くあるのだ。このパターンは英語圏で「IIFE」(イッフィー)とよばれる:「Immediately-invoked function expression」。つまり即時に実行される関数エクスプレッション。まあ、コードを見ればそういうもんですね。(@spacelogueさんによると日本語では即時関数というんだって)

まあそれはそれで良いんだが、何のために使うのだろう?答えは、オブジェクト指向の要件の一つであるカプセル化を実現するためである。JavaScriptにはクラスもブロックスコープもないので、モジュールの内蔵を周りから隠すにはクロージャを使うしかない。関数が実行されることによって出来るクロージャの中身は隠されるし、IIFEに渡される変数はクロージャの中でありのままに残るので、クラスのプライベートメンバみたいな実装になる:

var n = 1;

var savedN = (function(x) {
return x;
})(n);

n = 999;
console.log(savedN); // 1

そしてモジュールにはパブリックメソッドや変数も必要。それを実装するには、IIFEの戻り値をオブジェクトにする。戻り値のオブジェクトに定義されるメソッドは、外から呼ばれてもクロージャの中のスコープで実行されるので、モジュール的な実装ができる:

var hoge = (function(){
var n = 0;
return {
getN: function(){
return n;
},

setN: function( x ){
n = x;
}
}
})();

hoge.setN(99);
hoge.getN();  // 99
hoge.n;  // エラー

これがJavaScriptの「モジュールパターン」。ちなみに、上記のJSはAS3としてでも問題なくコンパイル出来るので、やろうと思えばAS3ででもIIFEを使える。必要ないと思うが!