querySelectorAllおよびgetElementsBy *メソッドは何を返しますか?


151

DO getElementsByClassName(など、同様の機能getElementsByTagNamequerySelectorAll)仕事と同じgetElementByIdか、それが要素の配列を返すのですか?

私が尋ねる理由は、を使用してすべての要素のスタイルを変更しようとしているためですgetElementsByClassName。下記参照。

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

37
手がかりは、その名のgetElementsByClassName()とおりです。複数を意味し、一方getElementById()、単数要素の項目を意味します。
デビッドはモニカを復活させると

1
配列をループする代わりに、上記のコードを使用してそのクラス名のすべての要素を変更することはできないということは、私には理解できませんでした。jqueryの方法ははるかに優れています。私はjsの方法に興味がありました
dmo

1
あまりにも役に立つかもしれない:stackoverflow.com/questions/3871547/...
カパ

回答:


152

あなたのgetElementById()IDは一意である必要があり、したがって、関数は常に1つの要素を返します(または以降のコードは動作しますnullが見つからなかった場合)。

しかし、getElementsByClassName()querySelectorAll()、および他のgetElementsBy*方法は、要素の配列のようなコレクションを返します。実際の配列と同じように繰り返します。

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

もっと短いものが好きな場合は、jQueryの使用を検討してください。

$('.myElement').css('size', '100px');

1
それはまたに適用されます<iframe>これは、あなたのドメインの一部である
JMASTER B

3
それは2018年です...のラッパー関数を作成するだけでquerySelectorAll()、古き良き大規模な依存関係なしに、素敵な短いコードを作成できます。qSA(".myElement").forEach(el => el.style.size = "100px")ラッパーにコールバックを受信させることができます。qSA(".myElement", el => el.style.size = "100px")

2
「もっと短いものを使いたい場合は、プロジェクトに巨大なライブラリを追加することを検討してください。」2012年は別の時期だったと思いますが、それでも、それはちょっと馬鹿げていると思いました。
CoryCoolguy

1
あなたのような、それを反復が本当の配列...と考え慎重に、のgetElementsByClassNameを返しライブ彼らはによって選ばれたことをクラス名が削除された場合、予想外ループ、例えば中に変更される可能性がありますのNodeListを;-)。
RobG

20

あなたがオブジェクトとして配列を使用している、との違いgetElementbyIdとは、 getElementsByClassNameその次のとおりです。

  • getElementbyIdElementオブジェクトを返します。IDの要素が見つからない場合はnull を返します。
  • getElementsByClassName一致する要素が見つからない場合、長さ0のライブHTMLCollectionを返します

getElementsByClassName

このgetElementsByClassName(classNames)メソッドは、クラスを表す、スペースで区切られた一意のトークンの順序付けされていないセットを含む文字列を取ります。呼び出されると、メソッドNodeListは、引数で指定されたすべてのクラスを持つドキュメント内のすべての要素を含むライブオブジェクトを返し、 スペースで文字列を分割してクラスを取得する必要があります。引数にトークンが指定されていない場合、メソッドは空のNodeListを返す必要があります。

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

getElementById

getElementById()メソッドは、指定されたIDの最初の要素にアクセスします。

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

あなたのコードで行:

1- document.getElementsByClassName( 'myElement')。style.size = '100px';

は配列を返し、配列にはプロパティがないため、期待どおりに機能しません。それらを反復処理することにより、それぞれにアクセスできます。getElementByClassNamestyleelement

これが関数が機能した理由getElementByIdです。この関数は直接オブジェクトを返します。そのため、style宿泊施設にアクセスできます。


注ことWHATWG仕様のブラウザで実装されていませんここでは、W3Cのものとは異なる、旧(ひいては現在のブラウザは)のgetElementsByClassNameためHTMLCollection、ないのNodeListを返します。マイナーですが、混乱する可能性があります。
海洋堂

@海道—実際の違いは…?私の理解では、NodeListはDOM要素の一般的なコレクションであり、HTML DOM(たとえば、XML DOM)だけでなく、すべてのDOMで使用できますが、HTMLCollectionはHTML DOM(当然)用です。私が見ることができる唯一の違いはあるnamedItemの方法HTMLCollection
RobG

PS Nit pick:WHATWG HTML Living StandardおよびW3C HTML 5.2標準へのリンク。選択によって甘やかされて育った。;-)ただし、あなたが提起したポイントに違いはありません。
RobG、

@RobG NodeListには、HTMLCollectionではアクセスできない多くのメソッドがあります。
海洋堂

@Kaiido —確かに、forEachはW3CまたはWHATWGによってコレクションまたはNodeListのいずれかのインターフェースの一部として指定されていません。たとえば、Web IDL仕様の汎用コレクションのプロパティとして個別に指定されているため、コレクションとNodeListの両方に適用する必要があります(ただし、getElementsByClassNameによって返されたコレクションにはforEachメソッドがないという点は認めます)。肝心なのは、良い答えがそれを伝えるのに十分なストーリーがあるということです。:-)
RobG

11

次の説明は、このページからの引用です

getElementsByClassName()メソッドは、指定されたクラス名を持つドキュメント内のすべての要素のコレクションをNodeListオブジェクトとして返します。

NodeListオブジェクトはノードのコレクションを表します。ノードにはインデックス番号でアクセスできます。インデックスは0から始まります。

ヒント:NodeListオブジェクトのlengthプロパティを使用して、指定されたクラス名を持つ要素の数を決定し、すべての要素をループして必要な情報を抽出できます。

そのため、パラメーターとしてgetElementsByClassNameクラス名を受け入れます。

これがHTML本文の場合:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

次に、指定されたクラス名と一致するため、var menuItems = document.getElementsByClassName('menuItem')上位3つの<div>のコレクション(配列ではない)を返します。

次に、このノード(<div>この場合はs)コレクションを次のように反復できます。

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

要素とノードの違いの詳細については、この投稿を参照しください。


11

ES6にArray.from()、配列のようなオブジェクトまたは反復可能なオブジェクトから新しいArrayインスタンスを作成するメソッドが用意されています。

let boxes = document.getElementsByClassName('box');

Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

コードスニペットの内部を見るとわかるように、Array.from()関数を使用すると、各要素を操作できます。


を使用した同じソリューションjQuery

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>


7

言い換えると

  • document.querySelector()指定されたセレクターの最初の1つの要素のみを選択します。だからそれは配列を吐き出さない、それは単一の値です。document.getElementById()IDは一意である必要があるため、ID要素のみをフェッチするのと同じです。

  • document.querySelectorAll()指定されたセレクターですべての要素を選択し、配列で返します。document.getElementsByClassName()クラスとdocument.getElementsByTagName()タグのみに似ています。


querySelectorを使用する理由

使いやすさと簡潔さの目的でのみ使用されます。


なぜgetElement / sByを使用するのですか?*

より高速なパフォーマンス。


なぜこのパフォーマンスの違いですか?

どちらの選択方法にも、後で使用するNodeListを作成する目的があります。 querySelectorsは、セレクターを使用して静的NodeListを生成するため、最初に最初から作成する必要があります。
getElement / sBy *は、現在のDOMの既存のライブNodeListをすぐに適合させます。

したがって、どの方法をいつ使用するかは、あなた/プロジェクト/デバイス次第です。


情報

すべてのメソッドのデモ
NodeList Documentation
Performance Test


4

配列のようなリストを返します。

あなたは例としてそれを配列にします

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

4

あなたは実行することで単一の要素を得ることができます

document.querySelector('.myElement').style.size = '100px';

しかし、クラス.myElementを持つ最初の要素に対して機能します。

これをクラスのすべての要素に適用する場合は、使用することをお勧めします

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

4
/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name


0

ドレンツィの特定のケースに対する答え ...

次のように、任意のword要素で機能する関数を作成し、変換する要素の番号を渡すことができます。

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.