Window オブジェクトや Document オブジェクト、DOM (Document Object Model) 、DOM 要素、jQuery オブジェクト等に関する個人的なメモ。
目次
ブラウザを操作するための機能を集めたオブジェクトがブラウザオブジェクトです。ブラウザオブジェクトは標準の規格があるわけではなく、個々のブラウザごとに独自に実装されています。(その中の Document オブジェクトは、ドキュメントオブジェクトモデル:DOM としてほぼ標準化されています。)
そのため以前はブラウザごとの仕様の違いによりクロスブラウザ問題がありましたが、現在では主要なブラウザではそれなりに互換性を持っています。
クライアントサイド JavaScript の階層構造で最上位に位置するオブジェクトが Window オブジェクト で、クライアントサイド JavaScript が起動するタイミングで自動的に生成されます。
ドキュメントを表示するウィンドウに対応するのが Window オブジェクトで、HTML ドキュメントに対応するのが Document オブジェクトになります。
以下はブラウザオブジェクトの階層構造です。
Window オブジェクトには、document プロパティや location プロパティがあり、document プロパティは、対応するウィンドウに関連付けられた Document オブジェクトを参照します。同様に、location プロパティは、対応するウィンドウに関連付けられた Location オブジェクトを参照します。また、自身を参照する window プロパティと self プロパティもあります。
クライアントサイドプログラミングでは Window オブジェクトがグローバルオブジェクトになり、どのグローバル変数も Window オブジェクトのプロパティとして定義されます。
(JavaScript の処理系では、スコープチェーンの先頭に1つのグローバルオブジェクトがあり、そのグローバルオブジェクトのプロパティがグローバル変数になります。)
次の2つコードは同じ意味になります。
var prop = 55; // グローバル変数を宣言し初期化 window.prop = 55; // Window オブジェクトに新たにプロパティを作成
以下のようにして確認することができます。
var prop = 55; console.log(prop); // 55と表示 window.prop = 77; // 普通はこのような書き方はしない console.log(prop); // 77と表示 prop = 88; console.log(prop); // 88と表示
例えば、Document オブジェクトの write メソッドにアクセスする場合、通常は以下のように直接 document プロパティを呼び出します。
document.write('Hello World!');
Window オブジェクトは自身を参照する window プロパティを持っているので以下のように記述することもできます(通常はこのような書き方はしません)。
window.document.write('Hello World!');
上記の window や document はプロパティ名であり、オブジェクト名ではありません。document は Document オブジェクトを参照するプロパティです。言い換えると、document プロパティは実態として Document オブジェクトを表しています。
デバッグのときなどに使用する alert() は Window オブジェクトのメソッドです。通常は自身を省略して記述しますが、自身を参照する window プロパティを記述しても同じことになります。
alert("message"); window.alert("message"); //同じこと
DOM (Document Object Model) は、ドキュメントを構成するオブジェクトにアクセスする方法を定義した API (Application Programming Interface) で、W3C が標準 DOM 仕様を定義しています。
DOM は JavaScript のようなプログラミング言語から、HTML ページにアクセスしてそれを操作する方法を提供しています。違った言い方をすると、ブラウザは HTML を読み込む際に、HTML の個々の要素をそれぞれに対応する DOM 要素に変換します。
クライアントサイドオブジェクトの階層構造では、Document オブジェクトから下位の階層がドキュメントオブジェクトモデル(DOM)になります。
以下のような HTML ページをブラウザはどのように処理をするか見てみます。
<html> <head> <title>Sample</title> </head> <body> <h1>HTML Document</h1> <p>This <i>sample</i> document...</p> </body> </html>
まずブラウザは、HTML のバイトを読み取ります。
そしてファイルに指定されているエンコード方法(UTF-8 など)に基づいて以下のような感じで個々の文字に翻訳します。
ブラウザは、文字列を W3C HTML5 標準で規定されている個々のトークンに変換し、続いて「オブジェクト」に変換します。
文書に含まれる要素や属性、テキストなどがオブジェクトに変換されます。
最後に、作成されたオブジェクトが、HTML で定義されているタグごとの関係性に基づき、ツリー型のデータ構造の中でリンクされます(HTML ドキュメントは 以下のような DOM ツリーで表現することができます)。
このプロセスの結果として、ページのドキュメント オブジェクト モデル(DOM)が構築されます。ブラウザはこれを利用して、その後のページの処理を行います。
文書を構成する要素や属性、テキストなどのオブジェクトをノードと呼びます。
ノードには、要素ノード (Element node)、テキストノード (Text node)、属性ノード (Attribute node)などがあります。
また、ノードはツリー型の階層構造になっています。例えば、html ノードは head と body ノードの親(Parent)ノードで、逆に head と body は html ノードの子(Child)ノードなどといいます。そして、 head と body は兄弟(Sibling)ノードと言ったりします。
JavaScript ではこれらのオブジェクトにアクセスして処理(操作)を行うことができます。
ドキュメント中の要素へアクセスするには、(JavaScript の)Document オブジェクトのメソッドを利用することができます。例えば、その要素に id 属性が付与されていれば、getElementById() というメソッドを使ってアクセスすることができます。
<p id="sample1">Sample paragraph 1</p>
上記のような p 要素がある場合、次のコードでアクセスすることができます。
var sample1 = document.getElementById('sample1');
この時、変数「sample1」には id 属性 sample1 がついた p 要素(を表すオブジェクト)が代入されています。
これ(変数「sample1」に代入されているもの)を DOM 要素とか DOM オブジェクト、要素オブジェクト、または JavaScript オブジェクトなどと呼んだりします。
そして例えば以下のように、innerHTML プロパティを使ってテキスト内容を取得したりすることができます。
var sample1 = document.getElementById('sample1'); var sample1_text = sample1.innerHTML; alert(sample1_text); //Sample paragraph 1 と表示される
DOM は標準化されているといっても、ブラウザごとにそれそれ少しずつ差異があります。 jQuery を使用するとこれらの差異を気にせずに操作ができます。
JavaScript では、DOM オブジェクトを操作するには、前述のように document.getElementById で要素を取得し、その innerHTML プロパティを操作したりしますが、jQuery では、非常に簡単に DOM オブジェクトにアクセスできます。
前述の JavaScript で行ったことを jQuery で行うと以下のようになります。(この例ではあまり違いはないように見えますが)
var sample1 = $('#sample1'); var sample1_text = sample1.text(); alert(sample1_text);
上記の変数「sample1」には id 属性 sample1 がついた p 要素を表す jQuery オブジェクトが代入されています。
jQuery オブジェクトは DOM 要素(DOM オブジェクト)ではありません。
この jQuery オブジェクトは、DOM 要素(DOM オブジェクト)を含む特別な JavaScript オブジェクトで、数多くの便利なメソッドなどが組み込まれています。
jQuery オブジェクトは、DOM 要素を jQuery で操作できるように加工したものと言えます。
jQuery オブジェクトを DOM 要素に変換するには、以下のような方法があります。
var sample1 = $('#sample1'); var sample1_DOM = $('#sample1')[0]; //[0] で DOM 要素を取り出す alert(sample1_DOM.innerHTML); //DOM 要素の innerHTML プロパティを使用 alert(sample1_DOM.text()); //jQuery オブジェクトのtext()メソッドにアクセスしようとするとエラーになる
var sample1 = $('#sample1'); var sample1_DOM = sample1.get(0); //get() で DOM 要素を取り出す alert(sample1_DOM.innerHTML); alert(sample1_DOM.text()); //エラーになる
逆に DOM 要素を jQuery オブジェクトに変換するには、以下のように $() で囲むだけです。
var sample1 = document.getElementById('sample1'); var sample1_jQ = $(sample1); alert(sample1_jQ.text()); //jQuery オブジェクトのtext()メソッドが利用できる
$() 関数は jQuery() 関数の別名です。
DOM 要素(の配列)を拡張機能によってラップする(包み込む)構造になっているので、この種の構造をラッパー(Wrapper)と呼んだりします。