ノードがメインページのDOMに接続される前に、ノードを頻繁に操作しています。また、特定のノードがメインドキュメントに含まれているかどうかに応じて、いくつかの作業を実行する必要があります。
私の現在の方法は、次の方法で両親を歩くことです。
if this.el$.closest("body").length > 0
これを行うためのより適切な方法はありますか?(できれば、ノードのすべての祖先を歩く必要がないものですか?)
いくつかの異なる速度で実行するいくつかのオプションがあります。
var $document = $(document);
var $element = $("#jq-footer");
var exists;
// Test if the element is within a body
exists = $element.closest("body").length;
// Test if the document contains an element
// wrong syntax, use below instead --> exists = $.contains($document, $element);
exists = $.contains(document.documentElement, $element[0]);
// Test if the element is within a body
$($element).parents().is("body");
// Manually loop trough the elements
exists = elementExists($element[0]);
// Used for manual loop
function elementExists(element) {
while (element) {
if (element == document) {
return true;
}
element = element.parentNode;
}
return false;
}
性能試験を見る
このテストでは、トラバースする大量の html をコピーしました。jQuery ページの 1 つのソースをフィドルにコピーし、すべてのスクリプト タグを取り除き、本文と html だけを残しました。
「本文」の代わりにドキュメントを使用したり、その逆を行ったり、さらにテストを追加したりしても構いませんが、一般的なアイデアが得られるはずです。
編集
パフォーマンス テストを更新して、containsの正しい構文を使用するようにしました。これは、前の構文が正しくなく、要素が存在しなくても常に true を返すためです。要素が存在する場合、打撃は true を返しますが、存在しないセレクターを指定すると false を返します。
exists = $.contains(document.documentElement, $element[0]);
また、質問のコメントにMrOBrianが言及した提案された代替案を追加しました。これは、含まれているよりもわずかに高速です。
素敵なMrOBrian。
編集
これは、すべての優れたチャートを使用した jsPerfパフォーマンス テストです。
問題を発見し、jsPerf テストの修正を手伝ってくれたFelix Klingに感謝します。
コメントからさらにテスト結果を追加しました。これは非常に優れています:
jsPerf performance test: dom-tree-test-exists
要素に ID を割り当てて、それを検索できます。
var id = element.id || generateRandomId(); // some function generating a random string
if(document.getElementById(id) !== null) {
// element in tree
}
これは、François の提案を含むパフォーマンス比較であり、接続された要素ノードと切り離された要素ノードの各メソッドを比較しています。速度の違いをよりよく理解するために、既存のノードのみのテスト ケースを次に示します。
試験結果:
デタッチされたノードを でテストすると、while
(2 回目の反復で) ほぼ瞬時に終了するため、明らかに高速です。しかし、ノードに (潜在的に) 切り離された祖先がある場合、ノードに ID を割り当ててそれを探すのが、Chrome 21 で最速の方法のようです。
興味深いことに、Firefox 14 では、Node#contains
[MDN]メソッドが他のどのメソッドよりもはるかに高速であるように見えます。
ID ルックアップからネイティブへの Firefox での速度の向上は.contains
、Chrome でのパフォーマンスの低下よりも大きいように見えるため、高速関数は次のようになります。
function in_tree(element) {
if(!element || !element.parentNode) { // fail fast
return false;
}
if(element.contains) {
return document.body.contains(element);
}
var id = element.id || generateRandomId();
element.id = id;
return document.getElementById(id) !== null;
}
しかし、最終的には、ブラウザー間には常に違いがあるため、妥協する必要があります。