web-dev-qa-db-ja.com

子ノードを取得するための最良の方法

不思議に思っていましたが、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;

私ができる限り、firstChildchildNodesからのNodeListを使い、firstElementChildchildrenを使います。私はこの仮定を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 タグはありません。

207

あなたがそれをひっくり返しているように思えます。 childNodeschildrenの違いを観察しました。それは、childNodesは、完全に空白からなるテキストノードを含むすべてのノードを含み、childrenは、要素である子ノードだけのコレクションであるということです。それだけで十分です。

注意すべき点がいくつかありますが、どちらのコレクションについても予測できないことはありません。

  • IE <= 8はchildNodesに空白のみのテキストノードを含みませんが、他のブラウザは含みます
  • IE <= 8はchildren内にコメントノードを含みますが、他のブラウザには要素しかありません

childrenfirstElementChild、およびfriendsは単なる便利なものであり、要素のみに制限されたDOMのフィルタリングされたビューを提示します。

198
Tim Down

firstElementChildはIE <9では使用できない可能性があります(firstChildのみ)。

mS DOM(IE <9)は空のテキストノードを格納していないため、IE <9のfirstChildはfirstElementChildです。しかし、他のブラウザでそうすると、空のテキストノードが返されます。

私の解決策

child=(elem.firstElementChild||elem.firstChild)

これはIE <9でも最初の子供になります

23
neu-rah

クロスブラウザによるやり方は、childNodesを使ってNodeListを取得し、次にnodeTypeELEMENT_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;
}

http://jsfiddle.net/s4kxnahu/

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がサポートされています です。

16
Gajus

こんにちはみんなはホワイトスペースをあなたをだまさせてはいけない。コンソールブラウザでこれをテストするだけです。ネイティブの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>
2
andre paradise

他の答えを追加するために、特に<svg>要素を扱うときには、ここでも注目すべき違いがあります。

私は.childNodes.childrenの両方を使っていて、.childrenゲッターによって提供されるHTMLCollectionで作業することを好みました。

しかし今日、私はIE/Edgeが.children<svg>を使用するときに失敗するという問題に遭遇しました。 .childrenは基本的なHTML要素のIEでサポートされていますが、 document/document fragment、 または SVG要素 ではサポートされていません。

私にとっては、気になる余分なテキストノードがないので、必要な要素を.childNodes[n]で簡単に取得できました。あなたは同じことをすることができるかもしれませんが、上記の他の場所で述べたように、あなたが予期しない要素に遭遇するかもしれないことを忘れないでください。

これが、.childrenがモダンなIE上のjsの他の場所で動作し、ドキュメントまたはSVG要素で失敗する理由を理解しようとしている誰かにとって役に立つことを願います。

2
slothluvchunk