263

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から NodeList を使用しchildNodes、 を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"…<コード>>. どうして?1 つのオブジェクトで「生の」HTML コードを操作でき、もう 1 つのオブジェクトで DOM に固執することは理解できますが、childNodes要素は両方のレベルで機能するようです。

最初の質問に戻ると、私の推測では次のようになります。最も包括的なオブジェクトが必要な場合childNodesは、その方法ですが、その包括性のために、必要な要素を返すという点で最も予測可能ではない可能性があります/いつでも期待できます。その場合、クロスブラウザーのサポートも課題になる可能性がありますが、私が間違っている可能性もあります。

手元にあるオブジェクトの違いを明確にできる人はいますか? 速度の違いがある場合は、ごくわずかですが、私も知りたいです。これがすべて間違っていると思われる場合は、お気軽に教えてください。


PS: お願い、お願い、私は JavaScript が好きなので、はい、このようなことを扱いたいと思っています。「jQuery はあなたのためにこれを扱っています」のような回答は私が探しているものではないため、タグはありません。

4

5 に答える 5

243

あなたはそれを考えすぎているように聞こえます。childNodesとの違いを確認しましたchildren。これは、childNodes完全に空白で構成されるテキスト ノードを含むすべてのノードを含み、childrenは要素である子ノードのみのコレクションです。本当にそれだけです。

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

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

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

于 2012-04-30T09:52:45.153 に答える
24

firstElementChild は IE<9 では使用できない場合があります (firstChild のみ)

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

私の解決策

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

これにより、IE<9でも最初の子が得られます

于 2012-04-30T09:33:39.940 に答える
23

クロスブラウザの方法はchildNodes、 get を使用してから、 ELEMENT_NODENodeListを使用してすべてのノードの配列を作成することです。nodeType

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

于 2014-11-24T10:18:54.570 に答える
5

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

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

しかし今日.children<svg>. .children基本的な HTML 要素では IE でサポートされていますが、ドキュメント/ドキュメント フラグメント、またはSVG 要素ではサポートされていません。

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

.childrenこれが、最新の IE の js の他の場所で機能し、ドキュメントまたは SVG 要素で失敗する理由を理解しようとして頭を悩ませている人に役立つことを願っています。

于 2016-06-21T17:44:57.730 に答える