[Javascript]  Javascript Pattern要約 - DOMとブラウザパターン

## DOMアクセス

DOMアクセス

・DOMアクセスは最小化する。
・ループ内でのDOMアクセスは避ける。

``` javascript
// アンチパターン
for (var i = 0; i < 100; i += 1) {
  document.getElementById("result").innerHTML += i + ", ";
}

// 変数を利用した改善
var i, content = "";
for (var i = 0; i < 100; i += 1) {
  content += i + ", ";
}
document.getElementById("result").innerHTML += content;
```
・DOM参照を変数に割り当てて使用する。

``` javascript
// アンチパターン
var padding = document.getElementById("result").style.padding,
    margin = document.getElementById("result").style.margin;

// 改善案
var style = document.getElementById("result").style.
    padding = style.padding;
    margin = style.margin;

document.querySelector("ul .selected");
// クエリーセレクターは他のDOMメソッド選択方式より速い。
```
・頻繁にアクセスするエレメントにid属性を追加するのも性能向上に役立つ。 なぜなら、`document.getElementById("id")`がノードを探す最も早い方法。

## DOM操作

DOM操作

・DOMアップデートは最小化した方が良い。
・アップデート時に画面をrepaintしてエレメントをreflowするのに費用がたくさんかかるため。
・サブツリーを追加する時は、サブツリーの構成要素をすべて生成した後、最後に一度だけ追加してくれる。

``` javascript
// アンチパターン
var p, t;
p = document.createElement("p");
t = document.createTextNode("first paragraph");
p.appendChild(t);
document.body.appendChild(p);

p = document.createElement("p");
t = document.createTextNode("second paragraph");
p.appendChild(t);
document.body.appendChild(p);

// 改善案
var p, t, frag;
frag = document.createDocumentFragment();

p = document.createElement("p");
t = document.createTextNode("first paragraph");
p.appendChild(t);
frag.appendChild(p);

p = document.createElement("p");
t = document.createTextNode("second paragraph");
p.appendChild(t);
frag.appendChild(p);

document.body.appendChild(frag);
```
・存在するツリーを変更する場合には、サブツリーのルートを複製して変更した後、元のノードと変える。

``` javascript
var oldnode = document.getElementById("result"),
    clone = oldnode.cloneNode(true);

oldnode.parentNode.replaceChild(clone, oldnode);
```

## イベント

イベントリスナーは以下のように実装できる。

``` javascript
var b = document.getElementById("clickme");
if (document.addEventListener) {
  b.addEventListener("click", myHandler, false);
} else if (document.attachEvent) {
  b.attachEvent("onclick". myHandler);
} else {
  b.onclick = myHandler;
}

function myHandler(e) {
    var src, parts;

    e = e || window.event;
    src = e.target || e.srcElement;

    if (src.nodeName.toLowerCase() !== "button") {
      return ;
    }

    parts = src.innerHTML.split(": ");
    parts[1] = parseInt(parts[1], 10) + 1;
    src.innerHTML = parts[0] + ": " + parts[1];

    if (typeof e.stopPropagation === "function") {
      e.stopPropagation();
    }
    if (typeof e.cancelBubble !== "undefined") {
      e.cancelBubble = true;
    }

    if (typeof e.preventDefault() === "funtion") {
      e.preventDefault();
    }
    if (typeof e.preventDefault() !== "undefined") {
      e.returnValue = false;
    }

}
```
・`setTimeOut()`や`WebWorker`を利用してスレッドのような機能を実現することができる。

## XMLHttpRequest

XMLHttpRequest

・JavaScript から HTTP リクエストを生成する特別なオブジェクト
・生成過程は以下の通りである。

``` javascript
var xhr = new XMLHttpRequest();

xhr.onreadystatechange = handleResponse;

xhr.open("GET", "page.html", true); 
xhr.send();
```

## JSONP

JSONP

・JSON with padding
・ブラウザの同一ドメインポリシーの制約を受けない。
・JSONPリクエストURL形態

``` javascript
http://example.org/getdata.php?callback=myHandler
```
・上でgetdata.phpがウェブページかスクリプトになることができる。
・getdata.php ファイルが受信されると、myHandler({"hello":"world"}) のようなコールバック関数が実行される。

## ウェブページロード戦略

ウェブページロード戦略

・scriptタグに入るエレメントを見てみよう。
・type="textjavascript":HTML5では必須属性ではなく、マークアップ有効性検査のための場合でなければ使用しない。
・async (defer):非同期スクリプトのロードで、スクリプトを受け取る間、他のダウンロードを妨げない。