如何判断节点是在内存中还是在dom中?

Jon*_*ton 6 jquery dom

在将节点附加到主页面的DOM之前,我正在使用节点.我需要执行一些工作,具体取决于给定节点是否包含在主文档中.

我目前的方法是通过以下方式走近父母:

if this.el$.closest("body").length > 0
Run Code Online (Sandbox Code Playgroud)

有没有更合适的方法来做到这一点?(首选一个不必走遍所有节点的祖先?)

Nop*_*ope 7

有几个选项可以以几种不同的速度执行.

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;
}?
Run Code Online (Sandbox Code Playgroud)

性能测试

对于这个测试,我复制了大量的html来遍历,我将其中一个jQuery页面的源代码复制到一个小提琴中,删除所有脚本标签,只留下主体和html介于两者之间.

您可以随意使用文档而不是"正文",反之亦然或添加更多测试,但它应该给您一般的想法.

编辑

我更新了性能测试以使用包含的正确语法,因为前一个不正确并且即使该元素不存在也始终返回true.如果元素存在,则现在返回true,但如果指定不存在的选择器,则返回false.

exists = $.contains(document.documentElement, $element[0]);
Run Code Online (Sandbox Code Playgroud)

我还在问题的评论中添加了MrOBrian提到的建议替代方案,该问题再次比包含的内容略快.

好一个MrOBrian.

编辑

这是jsPerf 性能测试,包含所有漂亮的图表.

感谢Felix Kling发现问题并帮助我修复jsPerf测试.

从评论中添加了更多的测试结果,这个非常好:
jsPerf性能测试:dom-tree-test-exists


Ale*_*lec 5

现代的香草答案是使用Node.isConnected

let test = document.createElement('p');
console.log(test.isConnected); // Returns false
document.body.appendChild(test);
console.log(test.isConnected); // Returns true
Run Code Online (Sandbox Code Playgroud)

(示例直接取自 MDN 文档)