【JavaScript】特定の要素を取得するメソッド querySelector/querySelectorAll
ペヤングが再発売されましたね。西日本出身の人間としては「カップ焼きそばといえば・・・論争」でいつも関東の人とケンカになります。
ペヤングがそもそも売ってないんですよね。関東にいる今でもカップ焼きそばは「U.F.O.」派な Latin です。
さて今回は、JavaScript でDOM操作をしたい時には色んな方法がありますが、処理速度やパフォーマンスなどの観点から、どの処理方法がベストなのか、検証と勉強も兼ねて調査してみました。
今回のサンプルは実際に案件であったものです。
やりたい事は以下のようなことです。
- div.container に新たな class 「full_column」 を付与したい。
- div.container はシステムテンプレートなので、直接編集する事ができない。
- 全てのページに 新classを付与する訳ではなく、必要なページにだけ付与したい。
その結果、ページ内コンテンツの中にインラインで JavaScript を記述する事になりました。
方法1. getElementsByClassName を使う
classを操作するんだから ClassName だね!って事で、まずは getElementsByClassName で試してみます。
getElementsByClassName は配列を返します。
コードはこんな感じ。
<script type="text/javascript">
// Container Full Size
var target = document.getElementsByClassName('container')[0];
target.className = "container full_column";
</script>
で、問題が発生。
IE8 で動かない!
そうなんです。getElementsByClassName は HTML5 で追加されたメソッドらしく、例の如く IE8 では解釈してくれません。
ライブラリ「getElementsByClassName.js」を使えば、IE8でも動作するようですが、少々重いようです。
ライブラリを追加するのもありだとは思うのですが、IE8 対応の場合、html5.js やら他の拡張ライブラリを実装しているケースも少なくないと思います。
getElementsByClassName を使う為だけにまた新たにライブラリを追加するのはちょっとなぁ・・・という感じ。
方法2. getElementsByTagName を使う
次に試したのが、
document.getElementsByTagName('div');
で div を拾ってきて、for で回して、className「container」を持つものを探させるという処理です。
コードはこんな感じ。
<script type="text/javascript">
// Container Full Size
var className = [];
var allElements = document.getElementsByTagName('div');
for (var i = 0, j = 0; i < allElements.length; i++){
if (allElements[i].className == 'container'){
var target = allElements[i];
target.className = "container full_column";
}
}
</script>
IE8 では無事動きましたが、
全ての div を拾って来るのはパフォーマンス的にも「なんだかなぁ~」と思ってしまいます。
方法3. querySelector を使う
querySelector を使えば、セレクタ指定とか jQuery ライクに書けて、IE8 でも使えます。
ただし、querySelector は複雑な処理をする目的で使われる事が多いようで、 中身を見てみると色んなものを引っ張って来てました。
IE8 を落として良い案件なら、getElementsByClassName を使った方が良さそうです。
<script type="text/javascript">
// Container Full Size
var target = document.querySelector('.container');
target.className = "container full_column";
</script>
表示速度の計測結果
Chrome Developer Tools で 表示速度をざっくり計測してみました。
getElementsByClassName | 838ms(Load 942ms / DOMContentLoad 570ms) |
---|---|
getElementsByTagName | 894ms(Load 934ms / DOMContentLoad 638ms) |
querySelector | 865ms(Load 911ms / DOMContentLoad 589ms) |
こんなもんですかね・・・。
今回は特定の一つのセレクタを操作という単純な処理だったので、目に見えるほどの差は見られなかったんですが、
処理がより複雑化すると差が出てくるんでしょうか。
実際の案件では、対象ブラウザが IE8 以上で、当初は getElementsByTagName を使って処理をしていましたが、これはやっぱり重いんだなっちゅう事で、querySelector を採用しました。
この辺りは臨機応変に考察した方が良さそうですね。
参考
- [JS] IE8にも対応できるクラス名から要素を取得する方法
http://memocarilog.info/javascript/7021