如何在纯javascript中获取给定元素的所有父节点?

如何在纯javascript中获取给定元素的所有父节点?,javascript,dom,Javascript,Dom,我指的是一系列的。这是从顶部HTML到目标元素(包括元素本身)的链 例如,对于元素,它将是: [HTML, BODY, DIV, DIV, P, SPAN, A] 您可以尝试以下方法: var nodes = []; var element = document.getElementById('yourelement'); nodes.push(element); while(element.parentNode) { nodes.unshift(element.parentNode)

我指的是一系列的。这是从顶部HTML到目标元素(包括元素本身)的链

例如,对于元素
,它将是:

[HTML, BODY, DIV, DIV, P, SPAN, A]

您可以尝试以下方法:

var nodes = [];
var element = document.getElementById('yourelement');
nodes.push(element);
while(element.parentNode) {
    nodes.unshift(element.parentNode);
    element = element.parentNode;
}
稍微短一点(而且更安全,因为可能找不到
target
):

大概是这样的:

var nodeList = [document.getElementById('element')];
while (nodeList[nodeList.length - 1].parentNode !== document) {
    nodeList.unshift(nodeList[nodeList.length - 1].parentNode);
}

我相信,如果您经常使用此功能,从长远来看,在大多数情况下,这可能是最有效的。t之所以会表现得更出色,是因为它首先会检查它可能遇到的祖先的深度。此外,该函数不会在每次调用时创建一个新数组,而是会高效地重用同一个数组,并对其进行切片,这在某些浏览器中是非常优化的。然而,由于我所知道的没有真正有效的方法来检查最大深度,所以我只能使用效率较低的查询选择器检查

// !IMPORTANT! When moving this coding snippet over to your production code,
// do not run the following depthtest more than once, it is not very performant
var kCurSelector="*|*", curDepth=3;
while (document.body.querySelector(kCurSelector += '>*|*')) curDepth++;
curDepth = Math.pow(2, Math.ceil(Math.log2(startDepth))),
var parentsTMP = new Array(curDepth);

function getAllParentNodes(Ele){
    var curPos = curDepth;

    if (Ele instanceof Node)
      while (Ele !== document){
        if (curPos === 0){
          curPos += curDepth;
          parentsTMP.length <<= 1;
          parentsTMP.copyWithin(curDepth, 0, curDepth);
          curDepth <<= 1;
        }
        parentsTMP[--curPos] = Ele;
        Ele = Ele.parentNode;
      }
    return retArray.slice(curPos)
}
/!重要!将此代码段移到生产代码中时,
//不要多次运行以下深度测试,它的性能不是很好
var kCurSelector=“*|*”,curDepth=3;
while(document.body.querySelector(kCurSelector++'>*|*'))curDepth++;
curDepth=Math.pow(2,Math.ceil(Math.log2(startDepth)),
var parentsTMP=新数组(curDepth);
函数getAllParentNodes(Ele){
var curPos=curDepth;
if(节点的元素实例)
while(Ele!==文档){
如果(curPos==0){
curPos+=curDepth;
parentsTMP.length另一种选择(基于):

我喜欢这个方法:

[...(function*(e){do { yield e; } while (e = e.parentNode);})($0)]
…其中$0是您的元素

此方法的一个优点是它可以用作表达式中的值

要获取不包含目标元素的数组,请执行以下操作:

[...(function*(e){while (e = e.parentNode) { yield e; }})($0)]

+1.也比我快,但不是在结尾使用
reverse()
,我只会使用
unshift()
而不是
push()
是的,而不是在结尾使用reverse,使用unshift将是一种更有效的方法。答案已编辑。@techfoobar技术上
push()
reverse()
更快,因此这取决于您对“高效”的定义。这真的取决于函数的使用情况,如果没有使用性能关键部分,
unshift
对我来说感觉更自然。如果这是一条关键路径,那么我会选择前者。+1作为信息。仍然unshift会使代码看起来比推送和反转更干净。如果我们不处理数组,我想性能不会很明显。+1.一直以来我都不知道
。push()
有一个兄弟叫
。unshift()
!我改变了公认的答案。这是最优雅的。(顺便说一句,测试表明,先推后反转更有效。)[我希望有一个选项可以接受多个答案,即使是以我的分数为代价。]这将包括文档节点。如果您希望停止在
HTML
元素,那么将'a=a.parentNode'更改为
a=a.parentElement
更优雅,只是为了好玩:
const parents=node=>(node.parentElement?parents(node.parentElement):[]).concat([node]);
@rsk82 9.5年后和
push
+
reverse
仍然快了400%。哇,这是迄今为止最短的解决方案。如果你想删除目标元素本身,你可以在
.slice(1)
末尾添加,如果你想先拥有最棒的父元素,
.reverse()
为了排除目标元素,更容易将do-while反转成这样的while循环:
[…(函数*(e){while(e=e.parentNode){yield e;}}}($0)]
(我已经更新了答案)
[...(function*(e){do { yield e; } while (e = e.parentNode);})($0)]
[...(function*(e){while (e = e.parentNode) { yield e; }})($0)]