スクリプトは(function(){ ... }())でくくれ。

最近のJavaScriptを見ているとこんな感じになっているものが多い。

(function(){
	...
}());

よくGoogle Analyticsのコードで見かけると思う。これは、スクリプトが呼び出されたときにすぐ実行されるという意味である。

さて、マニアックなコードを書く人は、よくwindowオブジェクトとdocumentオブジェクトはキャッシュするべきという。具体的には、

	var _window = window;
	var _document = document;

みたいに最初に宣言して、あとは、_document.getElementById('hoge')見たく書かくのだ。これによって、ブラウザによっては、若干の高速化が図れる。これと、クロージャーを合わせるとわざわざこんな宣言しなくても済む。

(function(window, document){
	...
} )(this, this.document );

(function(window, document){(window, document)は、(this, this.document)にそれぞれ格納されるため、オブジェクトキャッシュと等価になる。なんで、windowthisに化けてるって?それは、ブラウザにおいてはwindowオブジェクトが一番上位のオブジェクトになるためである。したがって、document.getElementById('hoge')は、厳密にはwindow.document.getElementById('hoge')と書くべきだし、それでも動作する。

この方法のメリットは、YUI CompresserやGoogle Closureなどでスクリプトを圧縮したときに、圧縮効率が飛躍的に向上するところである。

(function(window, document){
	var hoge = document.getElementById('hoge');
	window.alert(hoge.innerHTML);
} )(this, this.document );

みたいなコードを書くと、以下のような感じに圧縮される。

(function(a,b){
	var c=b.getElementById("hoge");
	a.alert(c.innerHTML);
})(this,this.document);

よく見て欲しい。先ほどfunction()の()内の変数は、末尾の})();の()内に格納されると書いた。圧縮した結果、aがthisに代入され、bがthis.documentに代入されてるのがわかる。

つまり、このクロージャー内のwindowオブジェクトやdocumentオブジェクトはすべてaとbに圧縮されることに他ならない。この工夫だけでもかなり容量が稼げる。

これに対し、そのまま内部を圧縮した場合は、documentもwindowも圧縮されない。

var a=document.getElementById("hoge");
window.alert(a.innerHTML);

応用として、最近では、jQueryのようなフレームワークを用いることが多い。プラグインによっては、以下のように書いてあることもある。

(function($, window, document){
	...
})(jQuery,this,this.document);

こうすることで、jQueryオブジェクトもキャッシュされるので高速化が図れるのだ。

ちなみに、dojoの場合はこう。

(function(dojo, dijit, dojox, window, document){
	...
})(dojo, dijit, dojox ,this,this.document);