DOMによるWeb Application Clientの可能性

DOMにより、エレメントを見つけ出す

元々DOM(Document Object Model)は、W3Cによって策定された、XML文書をプログラムから操作する為のインターフェイスでした。

最新のDOMは、WHATWGにより策定され、実際にアプリケーションを作成するために必要な機能の、包括的なインターフェイスとなっています。

W3CのDOMでは触れられることが無かった、Windowオブジェクトに関してもインターフェイスが決められています。

おかげで、Webブラウザによる違いを吸収する労力が激減して、アプリケーションの開発に注力できるようになりました。

実際の仕様は、WHATWGにより策定された『DOM Living Standard』と、その『非公式な日本語訳』にあります。興味が有ればご覧ください。

見つける、ほしい物を

DOMで何かをする場合、対象となる要素(エレメント)を見つけなければなりません。このためのメソッドがいくつか用意されています。

下のボタンをクリックしてください。ボタンに記載されているコードに該当する要素に色がつきます。

["id_004"].childrenは、id_004の要素のchildrenフィールドと解釈してください(以下全て同じです)。

枠線で囲った7つの要素が対象です。全ての要素がDIVで、中のテキストがid属性とclass属性の内容です。

idid_001の要素の子要素がid_002id_003id_004の要素の子要素がid_005id_006になります。

idid_007の要素は、id_005の子要素でid_004の孫要素になります。

簡単な解説

最初の3つ(document.getElementByIddocument.getElementsByTagNamedocument.getElementsByClassName)は、W3CのDOMにも存在するメソッドです。

document.getElementById ('id_001')

引数のIDに該当する要素を返します。

HTML文書では、id属性がユニークと決められているので、返却される要素は必ず1つです。

document.getElementsByTagName ('div')

引数のタグ名称に該当する要素を返します。

該当する全ての要素を、NodeListとして返します。JavaScriptでは、返却値を配列として扱うことができます。

document.getElementsByClassName ('cls_002')

引数のクラス名称に該当する要素を返します。

該当する全ての要素を、NodeListとして返します。JavaScriptでは、返却値を配列として扱うことができます。

["id_004"].children

WHATWGのDOMで追加されたNodeオブジェクトのフィールド(DOMの仕様書では属性)です。

指定要素の全ての子要素です。子要素なので、孫要素の["id_007"]は対象外です。

W3CのDOMにも、よく似たフィールドNode.childNodesがありましたが、致命的な問題があり使い難いものでした(詳細は『ご注意(其の壱)』を参照してください)。

このフィールドのおかげで、随分楽になりました。

["id_004"].firstElementChild

WHATWGのDOMで追加されたNodeオブジェクトのフィールドです。

指定要素の最初の子要素です。

W3CのDOMにも、よく似たフィールドNode.firstChildがありましたが、致命的な問題があり使い難いものでした(詳細は『ご注意(其の壱)』を参照してください)。

このフィールドのおかげで、随分楽になりました。

["id_004"].lastElementChild

指定要素の最後の子要素です。

WHATWGのDOMで追加されたNodeオブジェクトのフィールドです。

W3CのDOMにも、よく似たフィールドNode.lastChildがありましたが、致命的な問題があり使い難いものでした(詳細は『ご注意(其の壱)』を参照してください)。

このフィールドのおかげで、随分楽になりました。

document.querySelector ('.cls_200')

WHATWGのDOMで追加されたNodeオブジェクトのメソッドです。

引数は、CSSのセレクターです。

CSSと同じパターンマッチの規則で、該当する要素を返します。複数該当した場合は、先頭の要素を返します。

このメソッドには少々問題があります。『ご注意(其の弐)』を参照の上、使用の可否を判断してください。

可能な限り、他のメソッドやフィールドの使用を考慮してください。

document.querySelectorAll ('.cls_002,.cls_200')

WHATWGのDOMで追加されたNodeオブジェクトのメソッドです。

引数は、CSSのセレクターです。

CSSと同じパターンマッチの規則で、該当する要素を全て返します。

このメソッドには少々問題があります。『ご注意(其の弐)』を参照の上、使用の可否を判断してください。

可能な限り、他のメソッドやフィールドの使用を考慮してください。

["id_001"].querySelectorAll ('.cls_002,.cls_200')

querySelectorAllは、特定の要素から呼ぶことで、その要素の子孫だけを対象にすることができます。

この例では、["id_001"]から呼び出しているので、対象はその子孫だけです。

["id_001"]の子孫にはcls_200classに設定している要素がないので、対象は["id_005"]だけとなります。

このメソッドには少々問題があります。『ご注意(其の弐)』を参照の上、使用の可否を判断してください。

可能な限り、他のメソッドやフィールドの使用を考慮してください。

ご注意(其の壱)

W3CのDOMに於けるNode.childNodesNode.firstChildNode.lastChildは、あくまでもNodeを対象としているので、返却値が要素(Element)とは限りません。

次のようなHTMLがあるとします。

<div id="id_01">
    <div id="id_02"></div>
    <div id="id_03"></div>
</div>

idid_01の要素の開始タグの後ろには改行があり、idid_02の要素の開始タグの前には空白があります。

これは、id_01要素の最初の子要素が、テキストノードであることを意味します。

そのため、["id_01"].firstChildは、テキストノードを返します。["id_01"].lastChildも同様です。

["id_01"].childNodesは、[テキストノード,["id_02"],テキストノード,["id_03"],テキストノード]を返します。

W3CのDOMしか使えないような環境では、注意してください。

ご注意(其の弐)

とっても遅いです。

下の表は、3000の要素を持つドキュメントから、各メソッドを使って、該当の要素を呼び出し回数行の回数、繰り返し抽出した時の、経過時間です。

例えば一番左の列は、getElementByIdを、1億回繰り返し呼び出したときに、何ミリ秒かかったかということです。

繰り返し回数がそれぞれのメソッドで異なるのは、同じ回数では到底テストできないレベルの違いがあるからです。

テストを行ったメソッドと引数は、以下のとおりです。

document.getElementById('id_10599');
document.querySelectorAll('#id_10599');
document.getElementsByClassName('CLS2_200');
document.querySelectorAll('.CLS2_200');
IDによる検索ClassNameによる検索
getElementByIdquerySelectorAllgetElementsByClassNamequerySelectorAll
呼び出し回数100000000回1000000回1000000回10000回
Firefox92618.62260
Google Chrome3949.6676.67.4231.4
Microsoft Edge18980.217146.2684.6218.6

結果は、同じテストを5回実施した平均です。

テストは、Linuxの仮想環境で動作する、Windows10の32ビット版で行っています。ディスクIOやネットワーク通信による影響は無いので、通常の環境と大きく異なることは無いと思います。

Firefoxの場合、getElementByIdquerySelectorAllでは、600倍以上、querySelectorAllの方が遅いことになります。

getElementsByClassNamequerySelectorAllでは、1万倍以上、querySelectorAllの方が遅いことになります。

呼び出し回数が異なるので、到底厳密なテストとは言えませんが、遅いということは感じられたのではないでしょうか?

旧版へのリンク

当コンテンツは、以前より公開している『DOMによるエレメントの操作』というコンテンツの、前半部分を新しい仕様を元に改訂したものです。

旧版では、仕様書のIDLなども記載していましたが、大幅な仕様改定もあり、新版ではIDLの記載は取りやめました。

『DOMによるエレメントの操作』の後半と、『DOMによるスタイルの操作』の内容は、次のコンテンツである『DOMにより、エレメントを変化(へんげ)させる』で、改定したものを公開しています。