Nicholas C. Zakas「getElementsByTagName()がquerySelectorAll()よりも高速な件」
NCZOnline 2010.9.28のエントリ
Why is getElementsByTagName() faster that querySelectorAll()?
- querySelectorAll()で取得されるNodeListは更新されない(static)件について
- getElementsByTagName()と比較して
- 処理の重さや、重くなる訳を仕様書やWebKitの実装を参照しながら説明して
- この2つのメソッドの使いどころを手短に記す
という主旨のエントリ
- 豆知識
- Scott Schillerは今Yahoo!のフェロー
- id:amachangの2008.3.6のエントリ「IE8 で実装された Selectors API とは何か?」でquerySelectorAll()/getElementsByTagName()の違いは分かりやすく書かれてる
以下斜め読んだ内容
- エントリ書いたきっかけ
- Scott Schillerのツイート
- ほぼ全てのブラウザで「getElementsByTagName("a")」が「querySelectorAll("a")」よりも高速、と
- jsPerf上で比較テストある
- 自分(Nicholas)とScottとRyan Grove(YUIチーム)でtwitter上で議論してみた
- 議論したことのフィードバックがこのエントリ
- Scott Schillerのツイート
- querySelectorAll()/getElementsByTagName()の違い
- 動的な(live)NodeLists
- DOMの不思議なところの1つ
- DOM Level 3 specに定義されてる
- HTML文書だとNodeLists=HTMLCollection
- 仕様書の該当箇所曰く
- NodeList(or NamedNodeMap)オブジェクトは動的(Live)
- DOMツリーに変更が入り、取得したNodeListに影響のある部分であれば、取得されたNodeListも変更される
- NodeList(or NamedNodeMap)オブジェクトは動的(Live)
- getElementsByTagName()は動的なNodeListsを返す
- liveなNodeListは使われてる
- 静的な(static)NodeLists
- 静的なNodeList取得
- 仕様書の該当箇所(Selectors API spec)曰く
- querySelectorAll()の戻り値は静的でないといけない
- DOMツリーへ加えられた変更は、querySelectorAll()使って取得されたNodeListへ反映させててはならない
- 取得時点でのNodeLists
//getElementsByTagName()例 //divs.lengthが増え続けるので、無限ループになる var divs = document.getElementsByTagName("div"), i=0; while(i < divs.length){ document.body.appendChild(document.createElement("div")); i++; } //querySelectorAll()例 //DOMツリー内のdiv要素の数が増えていくが //divs.lengthの数は変わらないので、ループは止まる var divs = document.querySelectorAll("div"), i=0; while(i < divs.length){ document.body.appendChild(document.createElement("div")); i++; }
- querySelectorAll()が(getElementsByTagName()より)速いわけ
- WebKitのソースコードを見ながら説明
- 動的なNodeListはDynamicNodeList.cppに定義
- 静的なNodeListはStaticNodeList.cppに定義
- 動的なNodeList
- 取得時点で対象となる要素すべてを走査していない
- 新規インスタンス作成時はキャッシュにオブジェクトを作成するだけ
- DynamicNodeList.cppの48行目以降
- オーバーヘッドはとても少ない。
- 生成済み動的なNodeListへアクセスするときは、document全体の変更点を問い合わせる
- lengthプロパティ(DynamicNodeList.cppの57行目以降)やitem()メソッド(DynamicNodeList.cppの109行目以降)の戻り値でわかる
- 静的なNodeList
- 取得時点でのスナップショットを作成しないといけないので、対象要素すべてを走査する必要あり
- 新規インスタンス作成時は、別ファイルにオブジェクトを作って、ドキュメント内のマッチする要素を全部チェックしてリスト作成する
- SelectorNodeList.cppの61行目以降にループ使って引数にマッチする要素をループ使ってチェックしてるのがわかる
- WebKitのソースコードを見ながら説明
- 使い分け
- コメント欄
あとでかく