不思議に思っていましたが、JavaScriptは任意の要素から最初の子要素を取得するためのさまざまな方法を提供していますが、どれが一番良いのでしょうか。つまり、動作に関しては、ほとんどのブラウザ間互換性があり、最速で、最も包括的で予測可能なものです。私がエイリアスとして使用するメソッド/プロパティのリスト:
var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]
これは両方の場合に機能します。
var child = elem.childNodes[0]; // or childNodes[1], see below
これはフォームの場合、あるいは<div>
の繰り返しの場合です。私はテキスト要素に遭遇するかもしれないならば:
var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;
私ができる限り、firstChild
はchildNodes
からのNodeListを使い、firstElementChild
はchildren
を使います。私はこの仮定をMDN参照に基づいています。
childNode
は、要素ノードの最初の子要素への参照、または存在しない場合はnull
です。
firstElementChild
は事実上children[0]
への参照であり、children
オブジェクトはすでにメモリ内に存在しているため、速度の点では、違いがあっても違いはないと思います。
私を投げているのはchildNodes
オブジェクトです。私はこれを使って、フォーム要素、テーブル要素を調べました。 children
はすべてのフォーム要素をリストしますが、childNodes
はHTMLコードからの空白も含むようです。
console.log(elem.childNodes[0]);
console.log(elem.firstChild);
両方のログが<TextNode textContent="\n ">
console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);
すべてのログは<input type="text"
…>
です。どうして?片方のオブジェクトで「生の」HTMLコードを操作でき、もう一方でDOMを使用することができますが、childNodes
要素は両方のレベルで機能するようです。
私の最初の質問に戻るには、私が思うに、最も包括的なオブジェクトが欲しいのであれば、childNodes
がその方法です。 /いつでも期待しています。その場合、クロスブラウザのサポートも難しくなるかもしれませんが、私は間違っているかもしれません。
誰かが手元にあるオブジェクト間の違いを明確にすることができますか?ごくわずかですが、速度差がある場合は、私も知りたいです。私がこれをすべて間違って見ているならば、私を教育してください。
シモンズ:私はJavaScriptが好きなので、どうぞ、私はこのようなことに対処したいのです。 「jQueryがあなたに代わってこれを処理する」といった答えは、私が探しているものではないので、 jquery タグはありません。
あなたがそれをひっくり返しているように思えます。 childNodes
とchildren
の違いを観察しました。それは、childNodes
は、完全に空白からなるテキストノードを含むすべてのノードを含み、children
は、要素である子ノードだけのコレクションであるということです。それだけで十分です。
注意すべき点がいくつかありますが、どちらのコレクションについても予測できないことはありません。
childNodes
に空白のみのテキストノードを含みませんが、他のブラウザは含みますchildren
内にコメントノードを含みますが、他のブラウザには要素しかありませんchildren
、firstElementChild
、およびfriendsは単なる便利なものであり、要素のみに制限されたDOMのフィルタリングされたビューを提示します。
firstElementChildはIE <9では使用できない可能性があります(firstChildのみ)。
mS DOM(IE <9)は空のテキストノードを格納していないため、IE <9のfirstChildはfirstElementChildです。しかし、他のブラウザでそうすると、空のテキストノードが返されます。
私の解決策
child=(elem.firstElementChild||elem.firstChild)
これはIE <9でも最初の子供になります
クロスブラウザによるやり方は、childNodes
を使ってNodeList
を取得し、次にnodeType
ELEMENT_NODE を使ってすべてのノードの配列を作ることです。
/**
* Return direct children elements.
*
* @param {HTMLElement}
* @return {Array}
*/
function elementChildren (element) {
var childNodes = element.childNodes,
children = [],
i = childNodes.length;
while (i--) {
if (childNodes[i].nodeType == 1) {
children.unshift(childNodes[i]);
}
}
return children;
}
lodash などのユーティリティライブラリを使用している場合、これは特に簡単です。
/**
* Return direct children elements.
*
* @param {HTMLElement}
* @return {Array}
*/
function elementChildren (element) {
return _.where(element.childNodes, {nodeType: 1});
}
未来:
querySelectorAll
は、 :scope
擬似クラスと組み合わせて使用できます(セレクタの参照点である要素と一致します)。
parentElement.querySelectorAll(':scope > *');
この記事を書いている時点では、Chrome、Firefox、Safariでこの :scope
がサポートされています です。
こんにちはみんなはホワイトスペースをあなたをだまさせてはいけない。コンソールブラウザでこれをテストするだけです。ネイティブのJavaScriptを使用してください。これは、同じクラスを持つ2つの「ul」セットの例です。空白を避けるために、ulリストを1行にまとめて表示する必要はありません。配列数を使って空白を飛び越えるだけです。
querySelector()
その後childNodes[]
jsフィドルリンクで空白を回避する方法: https://jsfiddle.net/aparadise/56njekdo/
var y = document.querySelector('.list');
var myNode = y.childNodes[11].style.backgroundColor='red';
<ul class="list">
<li>8</li>
<li>9</li>
<li>100</li>
</ul>
<ul class="list">
<li>ABC</li>
<li>DEF</li>
<li>XYZ</li>
</ul>
他の答えを追加するために、特に<svg>
要素を扱うときには、ここでも注目すべき違いがあります。
私は.childNodes
と.children
の両方を使っていて、.children
ゲッターによって提供されるHTMLCollection
で作業することを好みました。
しかし今日、私はIE/Edgeが.children
で<svg>
を使用するときに失敗するという問題に遭遇しました。 .children
は基本的なHTML要素のIEでサポートされていますが、 document/document fragment、 または SVG要素 ではサポートされていません。
私にとっては、気になる余分なテキストノードがないので、必要な要素を.childNodes[n]
で簡単に取得できました。あなたは同じことをすることができるかもしれませんが、上記の他の場所で述べたように、あなたが予期しない要素に遭遇するかもしれないことを忘れないでください。
これが、.children
がモダンなIE上のjsの他の場所で動作し、ドキュメントまたはSVG要素で失敗する理由を理解しようとしている誰かにとって役に立つことを願います。