6

私はこのコードを作成しました:

var foo=document.createElement("div");

var childs=foo.getElementsByTagName("*");

console.log(childs.length);//0 OK

var a=document.createElement("a");

foo.appendChild(a);

console.log(childs.length);//1 WTF?

フィドル: http://jsfiddle.net/RL54Z/3/

childs=foo.getElementsByTagName("*");5行目から6行目までは書かなくていいのでchilds.length更新です。

どうしてですか?

4

2 に答える 2

3

DOM 内のノードのほとんどのリスト (たとえばgetElementsBy*、 、querySelectorAll、およびから返されるNode.childNodes) は単純な配列ではなく、むしろNodeListオブジェクトです。 NodeListドキュメントへの変更が自動的にオブジェクトに伝達されるという点で、オブジェクトは通常「ライブ」Nodelistです。(例外は、ライブquerySelectorAllではないからの結果です!)

例でわかるように、すべての要素の NodeList を取得してから、別の要素をドキュメントにa追加すると、NodeList オブジェクトに表示されます。aa

これが、ドキュメントを同時に変更しながら NodeList を反復処理することが安全でない理由です。たとえば、このコードは驚くべき方法で動作します。

var NodeListA = document.getElementsByTagName('a');

for (var i=0; i<NodeListA.length; ++i) {
   // UNSAFE: don't do this!
   NodeListA[i].parentNode.removeChild(NodeListA[i]);
}

何が起こるかというと、要素をスキップすることになります! NodeList の末尾から後方に反復するか、NodeList をプレーンな配列 (更新されません) にコピーしてから、それを操作します。

NodeList の詳細については、Mozilla MDC サイトを参照してください。

于 2012-06-30T05:18:57.463 に答える
3

ドキュメントを読んでも驚かないでしょう

指定されたタグ名を持つ要素のリストを返します。要素自体を除いて、指定された要素の下のサブツリーが検索されます。返されるリストはライブです。つまり、DOM ツリーで自動的に更新されます。したがって、同じ要素と引数で element.getElementsByTagName を何度も呼び出す必要はありません。

于 2012-06-30T05:12:11.567 に答える