オライリーの「JavaScriptパターン」を読んだ

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法


とりあえず動くjsは書けていろいろできる人向けの本な感じ。
こう書くといいよ。っていうパターンを教えてくれる。


以下、印象に残っているところ。

jsのどういうところに気をつけるべきか

  • グローバル変数簡単にできるのでバグの元
  • jsにクラスは存在しない
  • DOMのアクセスと更新はコストかかる

グローバル変数簡単にできるのでバグの元

この問題自体は知ってたけど、対策として"varつける"くらいしか知らなかった。

防ぎ方としては

  • 関数内にスコープができることを利用する
  • 名前空間つくって、その中で使う

この2つを組み合わせるといい感じだった。

jsは基本的にブロックスコープが存在せず、関数内にしかスコープが存在しない。
なのでグローバル空間を汚染したくなければ変数の宣言を関数内でしてやるのが良い。
そこで即時関数を利用してやる。

(function (){
    var hoge;  // ←こいつはローカル変数になる
})();

普通、jsの関数って宣言して呼び出さないと実行されないけど
即時関数は呼び出しいらずで実行される感じ。
なので、コードを全てこの即時関数で覆ってvarつけたらとりあえずグローバル汚染は防げる。


でもこれだと、例えばこの即時関数ないのメソッドとかは外から利用できなくなったり
オブジェクト指向的な使い方はできなくなるので
そういう使い方をしたいときは

名前空間をつくってその中で即時関数でメソッドを定義して使ってやる。

var MYAPP = MYAPP || {};

MYAPP.utilities = (function (){
    var util = {};

    util.start = function() {
        console.log("スタート!");
    };

    util.end = function() {
        console.log("おわり!");
    };
    return util;
})();

(function (){
    MYAPP.utilities.start();    // スタート!
    MYAPP.utilities.end();     // おわり!
})();

こう書いてやると
グローバル汚染せずにオブジェクト指向的な書き方ができる。
ここでのポイントはjsの関数はオブジェクトだということ。
関数がオブジェクトなので変数に持たせることができて
外から利用できる。

別のファイルからstart()やend()を呼びたいときは

var utilities = new MYAPP.utilities();
utilities.start();
utilities.end();

でクラスが存在しないにもかかわらず
コンストラクタ的な使い方ができる。

DOMの更新コストかかる

これも当たり前っちゃ当たり前なんですが
DOM操作はコストがかかる。

具体的には

  • DOM要素の取得
  • DOMの変更

この2つの処理には少し気を配る。

DOM要素の取得

// よくない例
$('.hoge').addClass('fuga');
$('.hoge').show();

// よい例
var $elem = $('.hoge');
$elem.addClass('fuga');
$elem.show();

こうやって複数回取得や操作が走る要素については
最初に変数に代入してやって、DOMへのアクセスを減らすといい。

DOMの変更

大幅なDOMの変更には
createDocumentFragmentを使ってやると
変更処理を高速化できる。

流れとしては
createDocumentFragmentで空の要素をつくり
その中に追加したい要素をappendしていき
最後に実際のDOMに対してcreateDocumentFragmentで作った要素を追加する。

これによってDOM操作の回数が大幅に減り、処理を高速化できる。

// 空の要素を生成
var frag = document.createDocumentFragment();

// fragに追加したい要素をappend
for (var i=0; i<100; i++){
    var numNode = document.createTextNode(i+", ");
    frag.appendChild(numNode);
}
// まとめてDOMにappend
document.body.appendChild(frag);

まとめ

特に印象に残ったパターンをまとめてみた。
他にももっと役立つパターンがこの本の中にはまとまっていて
それでいてページ数もそれほど多くないので、とても読みやすかった。