ログ日記

作業ログと日記とメモ

prototype.jsで綺麗なコードを書く

hawkさんにかなり助けてもらいつつ、コードが綺麗になってきたのでまとめてみる。
Ajaxイン・アクションの復習も兼ねて。


理解できてくると段々楽しくなってくるね。ブラウザの挙動の違いは困るけどprototype.jsが結構吸収してくれてるぽい。


HTMLからJavaScriptのコードを取り除く

知っている人は何を今更と思うかもしれないが、他の言語をやっていてJavaScriptに手を出そうとしたときに気付きにくい。入門書ではほとんどHTMLのタグの中に書いてるんだもの。

Event.observe(window, 'load', function(){
    // 初期化処理
    Initializer.initLink();
    Initializer.initForm();
});

ネットでもbodyタグにonload=hoge() としている例が沢山あるがそれは好ましくない。JavaScriptを外部ファイルにしきれていないのでちゃんと分ける。

オブジェクト指向で書く

上の例だと

var Initializer = {
    initLink: function(){
    },
    initForm: function(){
    }
}

のようなオブジェクトを定義しておいて名前空間を分ける。
または、

function Initializer(){
    this.initLink();
    this.initForm();
}
Initializer.prototype.initLink = function(){
}
Initializer.prototype.initForm = function(){
}

Event.observe(window, 'load', function(){
    var initializer = new Initializer();
});

でも良い。こちらはオブジェクトを複数扱ったり状態を保持したいとき向け。

イベントハンドラはリスナに登録する

汎用的にするには、onclick等に直接書かずにイベントリスナにハンドラ関数を登録する。

var Initializer = {
    initLink: function(){
        Event.observe('ajaxtext', 'click', function(){
            // Ajaxでリンク先を表示したりとか
        });
    },
    initForm: function(){
        Event.observe('form', 'submit', (function(e){
            if (this.checkFormError()){
                // 入力のエラーなど
                $('errorMessage').innerHTML = 'error!';
                Event.stop(e);
            }
        }).bind(this));
    },
    initInfo: function(menuItem){
        Event.observe(menuItem, 'click', this.viewInformation.bind($(menuItem)));
    },
    checkFormError: function(){...},
    viewInformation: function(){...}
}

イベントを登録するにはbindAsEventListener()の方が適しているようだが
http://blog.hawklab.jp/item-62.html
Event.observe()を使うならば必要ないっぽい。実際 bindAsEventListener()内で event||window.event としているだけだった。

$('form').onclick = this.myFunc.bindAsEventListener(this, arg1, arg2);

とobserveを使わない場合には有効だが、こっちを使う必要はなさそう。bind()のソースは$A(arguments)とかやっていてbindAsEventListener()の方はやってないのだが、この違いはまだ理解できていない。

# 追記
# なんか複数の引数(arg1, arg2)を受け取れなかった・・イベントだから引数はeventのみ?


イベントリスナは複数登録できる。onclickに対する動作を一カ所にまとめて書かなくてもいいようになる。
実行される順番は・・・不定だったような。実行される順番はIEのattachEventとaddEventListenerで逆(?)なので、複数登録する場合は互いに独立した関数にする。