behaviour.js リバースエンジニアリング その2

behaviour.js リバースエンジニアリング その1 は急いで書いたので、大事な部分を見落としてたように思うので、もうちょっと詳細に見てみます。


おもしろかったのはBehaviour.apply()の部分

	apply : function(){
		for (h=0;sheet=Behaviour.list[h];h++){
			for (selector in sheet){
				list = document.getElementsBySelector(selector);
				
				if (!list){
					continue;
				}

				for (i=0;element=list[i];i++){
					sheet[selector](element);
				}
			}
		}
	},

ユーザーが指定した「セレクタ名:関数」をプールしている配列Behaviour.listから、要素を抜きだして for 文で処理しているんですが。

for (h=0;sheet=Behaviour.list[h];h++){
	for (selector in sheet){
		list = document.getElementsBySelector(selector);

for〜in〜ステートメントで、sheetオブジェクト { セレクタ名:function(element){ ... } } から セレクタ名を抜き出してgetElementsBySelector()に渡しているのがなかなかスマート。getElementsBySelector()はセレクタ名を引数にとり、HTMLエレメントの配列を返す関数でした。なのでlistにはHTMLエレメントの配列が入る。

(このlist配列とBehaviour.list配列 は 別物なんですよね?名前が同じで、listは先に使われている名前だし、さらにvar宣言も無しに出てくるので違和感を覚える・・・)


そしてapply関数の後半では

		for (i=0;element=list[i];i++){
			sheet[selector](element);
		}

list配列からHTMLエレメントを抜き出してほげほげするんですが

sheet[selector](element);

がお見事な感じ。sheet[selector]で、{セレクタ名:関数} の関数名の部分をひっぱってきて 、()をつけて無名関数の部分を呼び出し実行しています。見慣れない構文だけど、これは関数の呼び出し式なんだな。悩んだ。



addLoadEvent()も面白いことをやってました。

addLoadEvent : function(func){
		var oldonload = window.onload;
		
		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				oldonload();
				func();
			}
		}
	}
}

addLoadEvenet()は関数を引数にとっています。ほほぅ。Javascriptだと関数も変数と同じように扱えるんだった。
で、

var oldonload = window.onload;

が不思議な式です。イベントハンドラを右辺で使うのは初めて見た。

		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				oldonload();
				func();

このような式があるので、ブラウザの実装の差を埋めるためのなんだと推測できますが・・・ここは知識足らずでしっかり説明できない部分が多い。