如何检查一个DOM元素是否是另一个DOM元素的子元素?有什么内置的方法吗?例如,像这样:

if (element1.hasDescendant(element2)) 

or

if (element2.hasParent(element1)) 

如果没有,有什么想法如何做到这一点?它还需要跨浏览器。我还应该提到,子对象可以嵌套在父对象的许多层之下。


当前回答

试试这个:

x = document.getElementById("td35");
if (x.childElementCount > 0) {
    x = document.getElementById("LastRow");
    x.style.display = "block";
}
else {
    x = document.getElementById("LastRow");
    x.style.display = "none";
}

其他回答

另一个没有提到的解决方案:

例子

var parent = document.querySelector('.parent');

if (parent.querySelector('.child') !== null) {
    // .. it's a child
}

元素是否为直接子元素并不重要,它在任何深度都可以工作。


或者,使用.contains()方法:

例子

var parent = document.querySelector('.parent'),
    child = document.querySelector('.child');

if (parent.contains(child)) {
    // .. it's a child
}

看一下node# compareDocumentPosition。

function isDescendant(ancestor,descendant){
    return ancestor.compareDocumentPosition(descendant) & 
        Node.DOCUMENT_POSITION_CONTAINS;
}

function isAncestor(descendant,ancestor){
    return descendant.compareDocumentPosition(ancestor) & 
        Node.DOCUMENT_POSITION_CONTAINED_BY;
}

其他关系包括DOCUMENT_POSITION_DISCONNECTED, document_position_precedand document_position_follows。

IE<=8不支持。

我只需要分享“我的”。

尽管在概念上与Asaph的答案相同(受益于相同的跨浏览器兼容性,甚至是IE6),但它要小得多,当大小非常重要或不经常需要时,它就会派上用场。

function childOf(/*child node*/c, /*parent node*/p){ //returns boolean
  while((c=c.parentNode)&&c!==p); 
  return !!c; 
}

..或者作为一行语句(只有64个字符!):

function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}

这里是jsfiddle。


用法: childOf(child, parent)返回boolean true|false。

解释: 只要While -condition的值为true, While就会计算。 && (AND)运算符在计算左边和右边之后返回布尔值true/false,但前提是左边为真(left && right)。

(&&)的左边是:(c=c. parentnode)。 这将首先将c的parentNode赋值给c,然后and运算符将计算得到的c作为布尔值。 由于如果没有父节点,parentNode将返回null,并且null将转换为false,因此当没有更多的父节点时,while循环将正确地停止。

右边(&&)是:c!==p。 ==比较运算符“不完全等于”。如果子结点的父结点不是你指定的父结点,它的值为真,但如果子结点的父结点是父结点,它的值为假。 如果c!==p的值为false,然后&&操作符返回false作为while条件,while循环停止。(注意这里不需要while-body和close;分号是必需的。)

因此,当while循环结束时,当c找到父节点时,它是一个节点(非空),或者当循环运行到最后没有找到匹配时,它是空的。

因此,我们只需返回该事实(转换为布尔值,而不是节点):return !!c;: the !(NOT运算符)反转布尔值(true变为false,反之亦然)。 !c将c(节点或null)转换为布尔值,然后才能反转该值。所以再加一个!(!!c)将这个false转换回true(这就是为什么使用double !!通常用于“将任何东西转换为布尔值”)。


额外的: 函数体/有效负载非常小,根据情况(比如它不经常使用,只在代码中出现一次),甚至可以省略函数(换行),只使用while循环:

var a=document.getElementById('child'),
    b=document.getElementById('parent'),
    c;

c=a; while((c=c.parentNode)&&c!==b); //c=!!c;

if(!!c){ //`if(c)` if `c=!!c;` was used after while-loop above
    //do stuff
}

而不是:

var a=document.getElementById('child'),
    b=document.getElementById('parent'),
    c;

function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}

c=childOf(a, b);    

if(c){ 
    //do stuff
}

试试这个:

x = document.getElementById("td35");
if (x.childElementCount > 0) {
    x = document.getElementById("LastRow");
    x.style.display = "block";
}
else {
    x = document.getElementById("LastRow");
    x.style.display = "none";
}

TL;DR:图书馆

我建议使用类似dom-helpers的东西,它是由react团队作为常规JS库编写的。

在它们的contains实现中,你会看到一个基于node# contains的实现,并带有一个node# compareDocumentPosition回退。

不支持非常老的浏览器,例如IE <9,我觉得这是可以接受的。

这个答案包含了上面的问题,但是我建议你不要循环。