JavaScriptの要素を取得するための自分用メモ。
メソッド書く前に毎度のごとく、単語の意味を復習。
HTMLElement
汎用的なHTMLの要素。
HTMLCollection
汎用的な要素ノードの集合。HTML要素以外のノードは含まない。配列風のオブジェクト。
リストから選択するためのメソッドとプロパティを提供する。
NodeList
ノードの集合体。名前の通りノード全般を含む。配列風のオブジェクト。
forEach
が使えるので、配列のように簡単に処理できる。
document.getElementById()
返り値:HTMLElement
指定したIDを持つ要素を返す。
要素が存在しない場合はnullを返す。
万が一、指定したIDをもつ要素が複数存在した場合は、最初に取得した要素のみを返す。
<span id="sample1">sample text</span>
const result = document.getElementById('sample1');
// result = <span id="sample1">sample text</span>
要素の中のテキストを取得する場合
const result = document.getElementById('sample1').textContent;
// result = sample text
document.getElementsByTagName()
返り値:HTMLCollection
指定したタグ名を持つ要素を返す。
<ul>
<li><span>test1</span></li>
<li>test2</li>
<li class="test3">test3</li>
</ul>
const result = document.getElementsByTagName('li');
// result = HTMLCollection(3) [li, li, li.test3]
document.getElementsByClassName()
返り値:HTMLCollection
指定したクラス名を持つ要素を返す。
<ul>
<li><span>test1</span></li>
<li>test2</li>
<li class="hoge">test3</li>
</ul>
<p class="hoge">hoge</p>
const result = document.getElementsByClassName('hoge');
// result = HTMLCollection(2) [li.hoge, p.hoge]
document.getElementsByName()
返り値:NodeList
指定したname属性の値を持つ要素を返す。
一般的にgetElementsByName
を使うのは、form
内の同じname属性
をもつ要素を取得する場合になるので他のメソッドと比べたら使う機会は少ない。
※ブラウザによって挙動が変わるので注意。
<input type="radio" name="q1" value="はい"> はい
<input type="radio" name="q1" value="いいえ"> いいえ
const result = document.getElementsByName('q1');
// result = NodeList(2) [input, input]
document.querySelector()
返り値:HTMLElement
指定したCSSセレクタとマッチする最初の要素を返す。
<div id="header">
<h1 class="title">titie</h1>
<p class="text">hoge</p>
<p class="text"><span>huga</span></p>
</div>
const header = document.querySelector('#header');
const title = document.querySelector('.title');
const text1 = document.querySelector('#header .text');
const text2 = document.querySelector('.text:last-child');
// header = <div id="header">
<h1 class="title">titie</h1>
<p class="text">hoge</p>
<p class="text"><span>huga</span></p>
</div>
// title = <h1 class="title">titie</h1>
// text1 = <p class="text">hoge</p>
// text2 = <p class="text"><span>huga</span></p>
querySelector()
のほうが直感的でわかりやすいが、
getElementById()
のほうが処理速度は早い。
document.querySelectorAll()
返り値:NodeList
指定したCSSセレクタとマッチする要素を返す。
<div id="header">
<h1 class="title">titie</h1>
<p class="text">hoge</p>
<p class="text"><span>huga</span></p>
</div>
const header = document.querySelectorAll('#header');
const text1 = document.querySelectorAll('.text');
const text2 = document.querySelectorAll('.text:last-child');
// header = NodeList [div#header]
// text1 = NodeList(2) [p.text, p.text]
// text2 = NodeList [p.text]
querySelectorAll()
のほうが直感的でわかりやすいが、
getElementsByTagName()
, getElementsByClassName()
のほうが処理速度は早い。
HTMLCollectionと動的なNodeList
HTML DOM 内の HTMLCollection は生きて (live) います。
NodeList には 生きた ものと 静的な ものの 2 種類のものがありますが、どちらも NodeList と考えられています。
例えば、 Node.childNodes は生きています。
生きた…?
<div class="content-wrap">
<p class="content">content1</p>
<p class="content">content2</p>
<p class="content">content3</p>
</div>
HTMLCollectionやNode.childNodes
const contentWrap = document.getElementsByClassName('content-wrap')[0];
const result = document.getElementsByClassName('content');
console.log(result);
// result = HTMLCollection(3) [p.content, p.content, p.content]
// contentWrapに要素を追加
contentWrap.insertAdjacentHTML('beforeend', '<p class="content">content4</p>');
console.log(result);
// result = HTMLCollection(4) [p.content, p.content, p.content, p.content]
基本的なNodeList
const contentWrap = document.querySelector('.content-wrap');
let result = document.querySelectorAll('.content');
console.log(result);
// result = NodeList(3) [p.content, p.content, p.content]
// contentWrapに要素を追加
contentWrap.insertAdjacentHTML('beforeend', '<p class="content">content4</p>');
console.log(result);
// result = NodeList(3) [p.content, p.content, p.content]
// 再取得すると変更が反映される
result = document.querySelectorAll('.content');
// result = NodeList(4) [p.content, p.content, p.content, p.content]
動的・・・現在の状態のDOM内の要素を取得する。DOMに変更が入ると即時反映される。
静的・・・生成した段階のDOMがコピーされるイメージ。DOMに変更が入っても生成したNodeListには影響しない。
例えば、動的の場合は取得した要素が3つのとき、取得した要素と同じ要素が4つに増えたら取得した要素も4つに増える。
静的の場合は取得した要素が3つのとき、取得した要素と同じ要素が4つに増えても取得した要素は3つのまま。
こんな感じ?なんとなく理解はできたけど言葉に落とし込めない…
注意
-
getElementById()
以外は配列型オブジェクトで返ってくるので、getElements~()
のs
を忘れないように。 - NodeListに対しては
forEach
が使える。
HTMLCollectionには使えないのでfor
を使用するかArray.from()
で配列に変換してからforEach
をするが、ぱっと調べたらforEach
よりfor
のほうが速度が早そうなのでわざわざ変換して使う必要はなさそう。
追記:データが莫大でない限り、速度気にする必要ないので使い慣れてるメソッドを使う。
使い分けとして
- idが付与されている要素なら
getElementById()
がやりたいこととしても処理速度的にもよさそう。 - 複数存在する要素の場合は
querySelectorAll()
が使いやすいけどプロジェクト内で決まりがあったり、単純にタグを指定したり単一のクラス名を指定する場合は処理速度も早いのでgetElements~()
を使うほうがよさそう。 - 要素が増減する場合は
getElements~()
を使う。
ご教示いただいた参照方法
関数を使うまでもない処理の場合(返り値はそれぞれの関数と同じ)
<div id="wrap">
<form id="f">
<input class="input">
</form>
</div>
getDcumentById()
const id = wrap;
// idの中の子要素をid指定で取得はできない
const form = wrap.f;
// 子要素を取得したい場合は以下の書き方
const form = wrap.children.f;
getElementsByTagName()
const form = document.forms;
// idを指定すれば指定されたidが付与されてるformを取得できる。
// 返り値は HTMLElement
const form = document.forms.f;
参考サイト:https://qiita.com/mashuel/items/83c8e0ad6b09590dfcbd
最後に
自分はこんな使い分け方してるよ~とかあったら教えてください。