JavaScript/DOM

出典: フリー教科書『ウィキブックス(Wikibooks)』
ナビゲーションに移動 検索に移動
イベント処理 JavaScript
DOM
ライブラリ

DOM(ドム、Document Object Model、ドキュメント・オブジェクト・モデル)とは、プログラミング言語からHTMLドキュメントなどを扱うために標準化された仕様です[1]。DOMをサポートするのはウェブブラウザ上のJavaScriptだけではありません。 JavaとDOMによるXML文書の操作や Node.jsjsdom の組み合わせの様なウェブブラウザ上のJavaScript以外の DOM 実装は存在します[2][3]。ウェブブラウザ上のJavaScriptにはDOM操作のためのDocumentオブジェクトが組み込まれています。

以前、このパラグラフでwindow.alertメソッドがDOMの一部であるとの記述が有りましたが、ウェブブラウザ上に警告ダイアログを表示するwindow.alertメソッドは Web API の一部ですがDOMの一部ではありません[4]

概要[編集]

HTMLのSCRIPT要素を用いると、JavaScriptのプログラムをHTMLドキュメントの中に埋め込むことができます。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Example Web Page</title>
    </head>
    <body>
        <div id="output">JaveScriptが無効です。</div>
        <scrip>
            const output = document.querySelector("#output");
            output.innerHTML = "Hello, world!";
        </script>
    </body>
</html>

このHTMLドキュメントをJavaScriptに対応したウェブブラウザで表示すると、ウェブページ上に "Hello, world!" という文字列が表示されます。 SCRIPT要素の中に書かれているJavaScriptプログラムのソースコードに注目してください。

document.querySelectorメソッドはDOMの一部で[5]、this(この場合は document)の子孫の中でCSSセレクタ "#output" と一致する最初の要素をツリー順に返し、一致する要素がない場合は null を返します。 ここでは "output" というIDを持つ要素、すなわち<div id="output"></div>というDIV要素を参照し、要素に対応するElementオブジェクトをoutputというconstな変数に代入しています。

output.innerHTMLプロパティを使用するとDIV要素の中身を取得したり設定したりすることができます。 ここではoutput.innerHTML"Hello, world!" という文字列を代入しているので、DIV要素の中身は "Hello, world!" という文字列になります。

動的なウェブページの操作[編集]

JavaScriptを学ぶ人は、ダイナミックなウェブページを作りたい人が多いと思います。

この項では、ウエブページの操作を行うパワフルな方法=DOMプログラミングを解説します。

サンプル[編集]

HTML文書やXML文書は、要素の中に0個以上の要素があり、その要素の中にも0個以上の要素がある。という入れ子構造をとっています。 この様な包含関係があるので、要素を含む要素を親要素、親要素に含まれている要素を子要素と呼びます。 そして、複数の要素を子として取れるため要素はツリー状に構成されます。 DOMとは、HTML文書やXML文書がツリー構造に基づいてデザインされた組み込み標準オブジェクトです。

まず、次のサンプルを打ち込んでください。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>DOMでのデータ取り出しテスト</title>
  </head>
  <body>
    <div>
      <p>DOM TEST</p>
    </div>
    <script>
        alert(document.querySelector("p").firstChild.nodeValue);
    </script>
  </body>
</html>

この文書では、HTML文書中のBODY要素にDIV要素が含まれており、その中にP要素、その中にテキストが埋め込まれています。 ここから「DOM TEST」の文字列を読み出したい場合はサンプルコードの様な記述をします。

では、解説していきます。 documentはDocumentインターフェイスのオブジェクトで特別に宣言を行わなくても存在し、これにはウェブページでの要素を頂点とする木構造として文書本体が格納されています[6]。 document.querySelector("p")は、DOMツリーの頂点からセレクタ "p"(P要素)を探し最初に見つかった要素を返します。 探したP要素の.firstChildプロパティで「内容」を得て、nodeValueプロパティで値(テキスト文字列)「DOM TEST」を得ている。

それぞれのメソッドとプロパティの解説を行うと、、

Document.querySelector(CSSセレクタ)
子要素から、CSSセレクタと一致する要素を探してElementとして返す
firstChild()
最初の子要素を返す
nodeValue
要素内のデータを取り出す

この様に、CSSセレクタとElementオブジェクトのプロパティを組み合わせ情報を読み出したり変更したりします。 そのため、DOMプログラムでは目的の1つあるいは複数の要素をCSSセレクタでどの様に表すかが重要になり、これは丁度CSSでスタイルシートを記述する時にCSSでプロパティを適用する要素を適切なCSSセレクタで記述する行為に対応している(CSSで書いたセレクタはそのまま querySelector や querySelectorAll で使えるので、スタイルシートでセレクタに一致する要素を背景色を変えてみるなどしてセレクタの働きを確認できる)。

基本的単語の解説[編集]

DOMはその名の中にある「ドキュメント」「オブジェクト」「モデル」の名の通り、マークアップされた文書の各部分をオブジェクト(モノ)として分割して、それぞれを参照して扱える様にする方法です。 マークアップされた文書内部には、タグで区切られた数々のデータがあり、それぞれを種類分けしてプログラムで扱っている。その中でも特によく使うDOMのデータ型は次の3種類である。

Node(ノード)
木構造の「節」。要素だけでなく属性 Attr を示す事もある。
Element(要素)
すべての要素オブジェクトが継承する基底オブジェクト
HEAD要素へのインターフェース HTMLHeadElement, BODY要素へのインターフェース HTMLBodyElement など要素オブジェクトはElement要素のプロパティを継承します。
Attr(属性)
DOM 要素の属性へのインターフェース

document.querySelector[編集]

document.querySelectorはDOMプログラミングを実際に行う際に最もよく使う機能で、指定したCSSセレクタの要素を参照することができます。 具体的には、

 var elem = document.querySelector("#sample");
 elem.firstChild.nodeValue = "てすと";

とする事で、sampleというidをも要素の内部のテキスト表示を置き換えます。

document.querySelectorAll[編集]

document.querySelectorはDOMプログラミングを実際に行う際によく使う機能で、指定したCSSセレクタと一致する要素をすべて返します。

コード例

const elms = document.querySelectorAll("li");
elms.forEach(el => el.style.color="red");

発見されたLI要素の文字色を赤にします。

DOMとCSSセレクタ
HTML+CSS+JavaScriptの技術基盤に基づくウェブコンテンツ制作において要素を指定する方法がCSS=CSSセレクタとDOM=getElementsBy*系メソッドと2つの異なる記法になってしましました。

このことは実装を複雑にし、誤解からバグの入り込む余地がありました。

この様な状況で、要素をCSSセレクタで指定できますjQueryなどのフレームワークがもてはやされました。

実際のコードを見てみましょう

getElementsByTagName("h1");
getElementsByClassName("className");
document.getElementById("sample");
getElementsByName("theName");

は、jQueryでは、

$("h1");
$(".className");
$("#sample");
$([name="thsName"]);

とCSSセレクタの書式で要素(へのラッパー)を得る等価な処理ができます。
ただこの方法では、ラッパーが間に入る続けるので冗長です[7]

この状況を憂慮して、DOMにもCSSセレクタを引数に要素を返すメソッドDocument.querySelector()とDocument.querySelectorAll()が追加されました[8]

document.querySelector("h1");
document.querySelectorAll(".className");
document.querySelector("#sample");
document.querySelector([name="thsName"]);

最初に見つかった要素が必要ならDocument.querySelectorメソッドを、一致する全てを得るならDocument.querySelectorAllメソッドを使います。

従来のDOMは、ツリー構造から特定の要素(または要素コレクション)を要素・クラス・ID・name属性を区別して適切なメソッドを選ぶ必要があり煩雑で、しばしばバグの原因となりましたが、 Document.querySelectorメソッド及びDocument.querySelectorAllメソッドの登場で、 CSSと同じセレクタで記述することができるようになり「スタイルシートとスクリプトで同じ要素を指定する手段が異なる」という捻じれ構造も是正することができました。

また、従来

const li = document.getElementsByTagName("li");
for (let i = 0, len = li.length; i < len; i++) {
  // li[i]に対する処理
}

を、Arrayイテレータを使い

const li = document.querySelectorAll("li");
li.forEach(el => /* elに対する処理 */)

と簡素に反復処理を行うことが可能となりました。

  • ノードの概念
    • DOMに関するオブジェクト

Attr CDATASection CharacterData Comment CustomEvent Document DocumentFragment DocumentType DOMException DOMImplementation DOMString DOMTimeStamp DOMStringList DOMTokenList Element Event EventTarget HTMLCollection MutationObserver MutationRecord NamedNodeMap Node NodeFilter NodeIterator NodeList NonDocumentTypeChildNode ParentNode ProcessingInstruction Range Text TimeRanges TreeWalker URL Window Worker

外部リンク[編集]

このページ「JavaScript/DOM」は、まだ書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にトークページへどうぞ。
  1. ^ かつてはW3CがDOMの標準化を行っていましたが、2021年6月現在ではWHATWGの策定する DOM Living Standard が標準です。 https://dom.spec.whatwg.org/
  2. ^ 元来、DOMは「プログラミングを言語に依存しない」オブジェクトモデリングシステムなので驚くに値しません
  3. ^ Abstract. DOM defines a platform-neutral model for events, aborting activities, and node trees. DOM Living Standard.
  4. ^ window.alert() [HTML Living Standard::8.8.1 Simple dialogs]で定義されています。[DOM Living Standard]ではありません。
  5. ^ https://dom.spec.whatwg.org/#dom-parentnode-queryselector
  6. ^ HTML4では頂点にフレームセットが来る可能性もありましたが、HTML5で廃止されました。
  7. ^ このおかげでメソッドチェーンが使えるのですが。
  8. ^ DOM Living Standard::4.2.6. Mixin ParentNode -- The querySelector(selectors) method steps are to return the first result of running scope-match a selectors string selectors against this, if the result is not an empty list; otherwise null.