連載
» 2008年05月08日 00時00分 公開

DOMの基本を学ぼう(4):NodeListの活用にはご注意を (1/2)

HTML上のタグ要素にアクセスする手法のおさらい。NodeListの活用法で気を付けるべき点、より実践的なHTMLでのメソッド使用法を学習しましょう。

[羽田野太巳,@IT]

旧来のDHTMLの手法では、JavaScriptから操作できるHTML要素には限りがありましたが、DOMでは、HTML上のありとあらゆる要素を自由自在に読み取ったり、書き換えることができるようになります。本連載では、主にDOM Level 1で規定されている手法を使い、JavaScriptでどのようにHTML上の要素へアクセスするのか、そして、それをどうやって書き換えるのかを詳しく解説します。これにより、JavaScriptからHTML要素を手に取るように操れるようになります。


 前回「ノード参照時におけるエラーハンドリング手法を学ぼう」では、タグの相対位置から要素を参照する方法と、ノード参照時のエラーハンドリングについて学習しました。今回は、HTML上のタグ要素にアクセスする手法のまとめとして、NodeListの活用法で気を付けるべき点と、より実践に近いHTMLでのメソッドの使い方、この2点を学習しましょう。

本連載は、ソフトバンククリエイティブ刊行の『標準DOMスクリプティング』のうち「第2章 DOMの基本」を、同社の許可を得て転載するものです。

本書は、DOM(Document Object Model)とJavaScriptの関係を分かりやすく解説しています。さらに、JavaScriptからDOMを介して、いかにしてHTMLやXMLの操作ができるのかを紹介しています。またこれらのことを学びながら、クロスブラウザ対策の重要性も理解できるようになると思います。

なお、 Webでの連載として転載するに当たり、若干表現を変更している点があります(例えば「本書は」としている部分は「本連載は」としていることや図版などの省略など)。その点ご了承ください。

【注文ページへ】


NodeListの用法にはご注意を

 getElementsByTagNameメソッドやchildNodesプロパティは、NodeListを返すということを学んできました。しかし「NodeList」という用語をあえて使ったのには訳があります。ここまで本書を読み進まれた方は、NodeListとはJavaScriptの配列のことと思われたのではないでしょうか。これまでのNodeListの使い方を見る限り、確かに配列と同じように扱ってきたので、勘違いされるのは当然です。実はNodeListとは、JavaScriptの配列、つまりArrayオブジェクトではありません。NodeListを配列として扱ってしまうと、期待する動作が得られず、デバッグに悩まされるでしょう。

 NodeListで使えるのは、itemメソッドとlengthプロパティのみです。それぞれを見ていきましょう。

 NodeListに3つの要素が格納されているとしましょう。最初の要素を取り出すためには、本来、itemメソッドを使います。

var nodeList = document.getElementsByTagName('div');
var elmObject = nodeList.item(0);

 itemはメソッドですので、( )を使ってインデックス番号を指定します。item[0]ではありませんので注意してください。

 インデックス番号は配列と同じく0から数えます。この例は、次の記法と同等です。

var elmObject = nodeList[0];

 DOMの規定では、どちらの記法を使ってもかまわないことになっています。これまで本書ではnodeList[0]という記法を使っていたため、NodeListをJavaScriptの配列と思われた方が多かったのではないでしょうか。NodeListはJavaScriptの配列ではありません。NodeListが、JavaScriptの配列と同じような記法で要素を取り出すことができるように作られているにすぎないのです。

 次にlengthプロパティですが、これはNodeListに格納されている要素数を取り出します。JavaScriptの配列で使うlengthプロパティと同じです。

var len = nodeList.length;

 変数lenには、nodeListの要素数が数字で格納されます。もしnodeListが空のリストであれば0となります。

 では、NodeListを配列と同じように使うことで、どのような問題が起こるのかを見てみましょう。最も顕著に違いが表れるのが、for/in文による繰り返し処理です。

nodelist_caution.html
<div>1つ目</div>
<div>2つ目</div>
<div>3つ目</div>
<script type="text/javascript">
/*DIVタグのノードリスト*/
var nodeList = document.getElementsByTagName('div');
/*for文による繰り返し処理で要素の内容を格納する*/
var forResult;
for(var i in nodeList) {
  forResult = forResult + i + "\n";
}
alert("*****for文の結果*****\n" + forResult);
</script>

 NodeListがJavaScriptの配列、つまりArrayオブジェクトであるならば、for文による繰り返し処理で変数iには配列のインデックス番号が格納され、アラートウィンドウには0、1、2と表示されると期待するでしょう。しかし実際にこのスクリプトを実行すると、次の図の通りになります。

DOM04 図1 Internet Explorer 6の場合、Firefox 1.5の場合、Opera 9の場合、Safari 2.0の場合

 このように結果は、期待通りにならないだけでなく、Webブラウザによっても異なります。Safariにいたっては1つもヒットしません。Webブラウザの差異をスクリプトで吸収するようなことは考えないでください。そもそも、NodeListはArrayオブジェクトではないのですから、使い方が悪いのです。

 NodeListの要素に対して1つずつ処理を行いたい場合は、同じfor文でも、インデックス番号を使う記法にしなければいけません。

 このfor文では、NodeListのlengthプロパティを使ってNodeListの要素数を取り出し、for文の評価式で使います。繰り返し処理の中では、該当の要素ノード参照オブジェクトを、itemメソッドにインデックス番号を与えて取り出します。

nodelist_caution.html
for(var i=0; i<nodeList.length; i++) {
/*要素ノードの参照オブジェクト*/
var elmNode = nodeList.item(i);
/*以下、要素ノードごとの処理*/
}

 もちろん、nodeList[i]という表記でもかまいません。その後、要素ノードごとの処理を書いていけばよいのです。

       1|2 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。