JavaScriptでのquerySelectorおよびquerySelectorAllとgetElementsByClassNameおよびgetElementById


165

私は正確に違いが何であるかを知っていただきたいと思いますquerySelectorし、querySelectorAll反対 getElementsByClassNameとはgetElementById

このリンクから、クラスで要素を取得し、IDで要素を取得querySelectorするように記述できることを収集できます。しかし、私はすでにそれを行うことができ、document.querySelector(".myclass")myclassdocument.querySelector("#myid")myidgetElementsByClassNamegetElementById。どちらを優先すべきですか?

また、IDがコロンで動的に生成され、次のように見えるXPagesで作業しview:_id1:inputText1ます。だから私が書いdocument.querySelector("#view:_id1:inputText1")てもうまくいきません。しかし、書き込みはdocument.getElementById("view:_id1:inputText1")機能します。何かアイデアはありますか?


1
querySelectorは、HTML要素とその属性をクエリのキー要素として含めることができるHTML DOMツリーのクエリに使用されます。これを行うには正規表現を使用できます。dojo.query()は同じことを行います
anix

1
どういう意味document.querySelectorAll(".myclass")ですか?を使用document.querySelector(".myclass")すると、一致する最初の要素のみが返されます。
mhatch

回答:


113

getElementsByClassNameおよびgetElementByIdに対するquerySelectorとquerySelectorAllの違いは何ですか?

構文とブラウザのサポート。

querySelector より複雑なセレクターを使用する場合に、より便利です。

例:fooクラスのメンバーである要素から派生したすべてのリスト項目: .foo li

document.querySelector( "#view:_id1:inputText1")機能しません。しかし、document.getElementById( "view:_id1:inputText1")を書き込んでも機能します。何かアイデアはありますか?

:文字は、セレクタ内で特別な意味を持っています。あなたはそれを脱出する必要があります。(セレクターのエスケープ文字はJS文字列でも特別な意味を持つため、エスケープする必要もあります)。

document.querySelector("#view\\:_id1\\:inputText1")

3
ブラウザごとに(また、バージョンごとに)異なります。私はセレクターベースのものがより高価だったと思います(しかし、重要になる可能性が高い方法ではありません)
Quentin

1
@janaspageのステートメントをサポートします。今日もサイトはダウンしています。
doplumi 2015年

6
クラスの選択については、jsperf.com/getelementsbyclassname-vs-queryselectorall/25も参照してください。結論:jqueryよりも純粋なJavaScriptと、特定の関数getElementByIdとを優先する必要がありgetElementsByClassNameます。なしでは、classNameの選択は数倍遅くなる可能性がありますgetElementsByClassName
アトラハシス

101

から収集 Mozillaドキュメント:

NodeSelectorインターフェースこの仕様は、Document、DocumentFragment、またはElementインターフェースを実装するオブジェクトに2つの新しいメソッドを追加します。

querySelector

ノードのサブツリー内で最初に一致するElementノードを返します。一致するノードが見つからない場合は、nullが返されます。

querySelectorAll

ノードのサブツリー内で一致するすべてのElementノードを含むNodeListを返します。一致が見つからない場合は、空のNodeListを返します。

そして

注:によって返されるNodeListはquerySelectorAll()ライブではありません。つまり、DOMの変更はコレクションに反映されません。これは、ライブノードリストを返す他のDOMクエリメソッドとは異なります。


32
+1は、ライブノードリストの区別を示します。これは、結果をどのように使用するかによって、知っておくべき非常に重要な違いです。
jmbpiano 2016

7
「ライブ」とは、DOMランタイムに追加されたノードを意味し、その新規に追加されたノードで動作できます
diEcho 2016年

83

違いについては、間の結果で重要なものがあるquerySelectorAllgetElementsByClassName:戻り値は異なっています。querySelectorAll静的コレクションをgetElementsByClassName返し、ライブコレクションを返します。後で使用するために結果を変数に保存すると、混乱が生じる可能性があります。

  • で生成された変数には、メソッドが呼び出されたquerySelectorAllときにセレクタを満たした要素が含まます。
  • で生成された変数には、使用時にgetElementsByClassNameセレクターを満たす要素が含まれます(メソッドが呼び出されたときとは異なる場合があります)。

たとえば、変数aux1andを再割り当てしていない場合でもaux2、クラスを更新した後、変数に異なる値が含まれていることに注意してください。

// storing all the elements with class "blue" using the two methods
var aux1 = document.querySelectorAll(".blue");
var aux2 = document.getElementsByClassName("blue");

// write the number of elements in each array (values match)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);

// change one element's class to "blue"
document.getElementById("div1").className = "blue";

// write the number of elements in each array (values differ)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);
.red { color:red; }
.green { color:green; }
.blue { color:blue; }
<div id="div0" class="blue">Blue</div>
<div id="div1" class="red">Red</div>
<div id="div2" class="green">Green</div>


2
ただ言及する-つまりdocument.getElementsByName、ノードリストを返すすべての古いDOM API 、document.getElementsByTagNameNSまたはdocument.getElementsByTagName同じ動作を示します。
RBT 2017年

2
一部の分析では、ここでdimlucas.com/index.php/2016/09/17/…のように、querySelectorはgetElementByIdよりも時間がかかるとしています。アクセス時間を考慮に入れるとどうなりますか?getElementByIdから取得したライブノードは、querySelectorからの静的ノードよりも時間がかかりますか?
エリック

1
@RBTこれらの古いDOM APIはNodeListオブジェクトを返さず、HTMLCollectionを返します。
Miscreant

@Eric document.getElementById()はライブノードを返しません。CSSセレクターを最初に解析する必要があるdocument.querySelector('#id_here')ため、おそらくそれよりも高速ですquerySelector
Miscreant

68

この回答のために、私はを参照querySelectorしてquerySelectorAllようquerySelector *とにgetElementByIdgetElementsByClassNamegetElementsByTagName、およびgetElementsByName getElementとして*。

主な違い

  1. querySelector *は、ID、タグ、またはクラスの単純なセレクターだけでなく、任意のCSS3セレクターを渡すことができるため、より柔軟です。
  2. querySelectorのパフォーマンスは、呼び出されるDOMのサイズによって変化します。*正確には、querySelector *呼び出しはO(n)時間で実行され、getElement *呼び出しはO(1)時間で実行されます。nは、呼び出された要素またはドキュメントのすべての子の総数です。この事実はあまり知られていないようですので、私はそれを大胆に述べています。
  3. getElement *呼び出しはDOMへの直接参照を返しますが、querySelector *は内部的に選択された要素のコピーを作成してから参照を返します。これらは「ライブ」および「静的」要素と呼ばれます。これは、返される型に厳密には関連していません。要素がある時点でコピーされたかどうかに依存し、データの固有のプロパティではないため、プログラムで要素がライブであるか静的であるかを知る方法はありません。ライブ要素への変更はすぐに適用されます-ライブ要素を変更するとDOMで直接変更されるため、JSの次の行でその変更を確認でき、その要素を参照する他のライブ要素にすぐに伝達されます。静的要素への変更は、現在のスクリプトの実行が完了した後にのみ、DOMに書き戻されます。
  4. これらの呼び出しの戻りタイプは異なります。querySelectorそして、getElementByIdの両方が単一の要素を返します。querySelectorAllまた、getElementsByNameどちらもNodeListを返します。これは、HTMLCollectionが古くなってから追加された新しい関数です。古いものgetElementsByClassNamegetElementsByTagName両方がHTMLCollectionsを返します。繰り返しますが、これは要素がライブであるか静的であるかには本質的に無関係です。

これらの概念を次の表にまとめます。

Function               | Live? | Type           | Time Complexity
querySelector          |   N   | Element        |  O(n)
querySelectorAll       |   N   | NodeList       |  O(n)
getElementById         |   Y   | Element        |  O(1)
getElementsByClassName |   Y   | HTMLCollection |  O(1)
getElementsByTagName   |   Y   | HTMLCollection |  O(1)
getElementsByName      |   Y   | NodeList       |  O(1)

詳細、ヒント、例

  • HTMLCollectionsは、NodeListsほど配列のようなものではなく、.forEach()をサポートしていません。これを回避するには、spreadオペレーターが便利です。

    [...document.getElementsByClassName("someClass")].forEach()

  • すべての要素、およびグローバルはdocument、これら以外のすべての機能にアクセスする必要がありgetElementByIdgetElementsByNameのみに実装されています、document

  • querySelector *を使用する代わりにgetElement *呼び出しをチェーンすると、特に非常に大きなDOMでパフォーマンスが向上します。小さなDOMや非常に長いチェーンでも、一般的には高速です。ただし、パフォーマンスが必要であることがわかっている場合を除き、querySelector *の読みやすさを優先する必要があります。querySelectorAllすべてのステップでNodeListまたはHTMLCollectionから要素を選択する必要があるため、多くの場合、書き換えが困難です。たとえば、次のコードは機能しませ

document.getElementsByClassName("someClass").getElementsByTagName("div")

because you can only use getElements* on single elements, not collections. For example:

`document.querySelector("#someId .someClass div")`

could be written as:

document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]

Note the use of `[0]` to get just the first element of the collection at each step that returns a collection, resulting in one element at the end just like with `querySelector`.
  • すべての要素がquerySelector *とgetElement *の両方の呼び出しにアクセスできるため、両方の呼び出しを使用してチェーンを作成できます。これは、パフォーマンスを向上させたい場合に役立ちますが、getElement *呼び出しに関して記述できないquerySelectorを回避することはできません。

  • 一般に、セレクターをgetElement *呼び出しのみを使用して作成できるかどうかを判断するのは簡単ですが、明らかでない場合があります。

    document.querySelectorAll(".class1.class2")

    次のように書き換えることができます

    document.getElementsByClassName("class1 class2")

  • querySelector *でフェッチされた静的要素に対してgetElement *を使用すると、querySelectorによってコピーされたDOMの静的サブセットに関しては有効ですが、完全なドキュメントDOMに関しては有効ではない要素になります...これが簡単な場所です要素のライブ/静的解釈はバラバラになり始めます。これについて心配する必要がある状況はおそらく避ける必要がありますが、そうする場合は、querySelector *が参照を返す前にそれらが見つけた要素をコピーしますが、getElement *呼び出しはコピーせずに直接参照をフェッチします。

  • 複数の一致がある場合、どちらのAPIも最初に選択する要素を指定しません。

  • querySelector *は、一致が見つかるまでDOMを反復処理するため(主な相違点#2を参照)、上記のことは、DOMで探している要素の位置に依存して、迅速に見つかることを保証できないことを意味します。ブラウザは、DOMを逆方向、順方向、深さ優先、幅優先などで反復できます。getElement *は、配置に関係なく、ほぼ同じ時間で要素を検索します。


4
このトピックについては、はるかに正確な答えです。もっと賛成する必要があります。
SeaWarrior404

Sasha
theking2

25

私は純粋にこのページにアクセスして、パフォーマンスの観点から使用するより良い方法を見つけました-つまり、より高速です:

querySelector / querySelectorAll or getElementsByClassName

そして私はこれを見つけました:https//jsperf.com/getelementsbyclassname-vs-queryselectorall/18

上記の2つの例でテストを実行し、さらにjQueryの同等のセレクターのテストも行います。私のテスト結果は次のとおりでした:

getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec

1
うわー、それは大きな違いです、調べてくれてありがとう。明らかquerySelectorAllに、背後で追加の作業(セレクター式の解析、疑似要素の説明などを含む)getElementsByClassNameが必要ですが、再帰的なオブジェクトトラバーサルです。
John Weisz

18

querySelector 次のように、IDとクラス、および疑似クラスを組み合わせた完全なCSS(3)-Selectorにすることができます。

'#id.class:pseudo'

// or

'tag #id .class .class.class'

getElementByClassNameあなただけのクラスを定義することができます

'class'

getElementByIdあなただけのIDを定義することができます

'id'

1
:first、今、CSSセレクタ?:first-class、あるいは:first-of-type多分、:firstJavaScript / jQuery / Sizzleの追加だと思いました。
デビッドはモニカ

@DavidThomasはい、そうです。CSS3の一部です。これは次のように使用できます:css-tricks.com/almanac/selectors/f/first-child
algorhythm

2
しかし:first、顕著ではありません:first-child
デビッドはモニカ

3
「セレクターでの疑似要素の使用は許可されていますが、ドキュメント内のどの要素とも一致しないため、結果として要素が返されないことに注意してください。したがって、疑似要素の使用は避けてください。この仕様で定義されているメソッドに渡されるセレクターの要素。」w3.org/TR/selectors-api/#grammar
リッチリマー2015

また、IEには(もちろん)疑似要素を選択すると、空の要素リストではなくルートHTML要素が返されるバグがあります。
リッチリマー

7

querySelectorそしてquerySelectorAll一方で、比較的新しいAPIですgetElementByIdし、 getElementsByClassNameはずっと以前から私たちと一緒にいます。つまり、使用するものは主に、サポートする必要のあるブラウザーによって異なります。

について:は、特別な意味があるため、ID /クラス名の一部として使用する必要がある場合はエスケープする必要があります。


13
これは必ずしも本当ではありません。たとえば、querySelectorAllはIE8で利用できますが、そうではありgetElementsByClassNameません。
DaveJ 2013

querySelectorAll...基本的にすべて:caniuse.com/#search=querySelectorAll
dsdsdsdsd

1

5

querySelectorw3c セレクターAPIの

getElementByw3c DOM APIの

IMOの最も顕著な違いは、の戻り値の型がquerySelectorAll静的ノードリストであり、getElementsByそれがライブノードリストであることです。したがって、デモ2でのループlisは、ライブであり、反復ごとに更新されるため、終了することはありません。

// Demo 1 correct
var ul = document.querySelectorAll('ul')[0],
    lis = ul.querySelectorAll("li");
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li"));
}

// Demo 2 wrong
var ul = document.getElementsByTagName('ul')[0], 
    lis = ul.getElementsByTagName("li"); 
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li")); 
}

4

「querySelector」と「querySelectorAll」の違い

//querySelector returns single element
let listsingle = document.querySelector('li');
console.log(listsingle);


//querySelectorAll returns lit/array of elements
let list = document.querySelectorAll('li');
console.log(list);


//Note : output will be visible in Console
<ul>
<li class="test">ffff</li>
<li class="test">vvvv</li>
<li>dddd</li>
<li class="test">ddff</li>
</ul>


2

これを見て

https://codepen.io/bagdaulet/pen/bzdKjL

getElementByIdが25%でquerySelectorよりも高速

jqueryが最も遅い

var q = time_my_script(function() {

    for (i = 0; i < 1000000; i++) {
         var w = document.querySelector('#ll');
    }

});

console.log('querySelector: '+q+'ms');

-3

querySelectorとgetlementbyID(Claassname、Tagname etc)の主な違いは、条件が満たされる要素が複数ある場合、querySelectorは1つの出力のみを返し、getElementBy *はすべての要素を返します。

より明確にするために例を考えてみましょう。

 <nav id="primary" class="menu">
                            <a class="link" href="#">For Business</a>
                            <a class="link" href="#">Become an Instructor</a>
                            <a class="link" href="#">Mobile Applications</a>
                            <a class="link" href="#">Support</a>
                            <a class="link" href="#">Help</a>
   </nav> 

以下のコードは違いを説明します

**QUERY SELECTOR**
document.querySelector('.link'); // Output : For Business (element)

document.querySelectorAll('.link'); //Out All the element with class link

**GET ELEMENT**
document.getElementsByClassName('link') // Output : will return all the element with a class "link" but whereas in query selector it will return only one element which encounters first.

簡単に言うと、単一の要素を選択する場合はqueryslectorに、複数の要素が必要な場合はgetElementに移動します。


1
getElementByIdは1つの要素のみを返します。これは2つの要素の違いではありません。
Timofey 'Sasha' Kondrashov '
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.