javascript - 在父节点中查找子节点索引的最快方法

标签 javascript html dom

我想找到 ID 为 'whereami' 的子 div 的索引。

<div id="parent">
   <div></div>
   <div></div>
   <div id="whereami"></div>
   <div></div>
</div>

目前我正在使用这个函数来查找 child 的索引。

function findRow(node){
    var i=1;
    while(node.previousSibling){
        node = node.previousSibling;
        if(node.nodeType === 1){
            i++;
        }
    }
    return i; //Returns 3
}

var node = document.getElementById('whereami'); //div node to find
var index = findRow(node);

fiddle :http://jsfiddle.net/grantk/F7JpH/2/

问题
当有上千个div节点时,while循环要遍历每个div来统计。这可能需要一段时间。

有没有更快的方法来解决这个问题?

*注意id会随着不同的div节点变化,所以需要重新计算才可以。

最佳答案

出于好奇,我针对两个 jQuery 的 .index() 运行了您的代码和我下面的代码:

function findRow3(node)
{
    var i = 1;
    while (node = node.previousSibling) {
        if (node.nodeType === 1) { ++i }
    }
    return i;
}

Jump to jsperf results

事实证明,jQuery 比您的实现(在 Chrome/Mac 上)慢大约 50%,而我的可以说是慢了 1%。

编辑

不能完全放弃这个,所以我又添加了两种方法:

使用 Array.indexOf

[].indexOf.call(node.parentNode.children, node);

我早期实验代码的改进,如 HBP's answer 中所示,DOMNodeList 被视为一个数组,它使用 Array.indexOf() 来确定其 .parentNode.children 中的位置,这些都是元素。我的第一次尝试是使用 .parentNode.childNodes 但由于文本节点而导致结果不正确。

使用 previousElementSibling

灵感来自 user1689607's answer ,最近的浏览器除了 .previousSibling 之外还有另一个名为 .previousElementSibling 的属性,它将两个原始语句合二为一。 IE <= 8 没有这个属性,但是 .previousSibling 已经这样做了,因此 feature detection会工作。

(function() {
    // feature detection
    // use previousElementSibling where available, IE <=8 can safely use previousSibling
    var prop = document.body.previousElementSibling ? 'previousElementSibling' : 'previousSibling';

    getElementIndex = function(node) {
        var i = 1;
        while (node = node[prop]) { ++i }
        return i;
    }

结论

在 IE <= 8 的浏览器上不支持使用 Array.indexOf(),而且仿真速度不够快;但是,它确实提高了 20% 的性能。

使用特征检测和 .previousElementSibling 产生了 7 倍的改进(在 Chrome 上),我还没有在 IE8 上测试它。

关于javascript - 在父节点中查找子节点索引的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13656921/

相关文章:

javascript - 在每次迭代时向 DOM 添加一个元素,而不是全部在循环结束时

javascript - 相机在 three.js 中找不到对象

javascript - 如何使用 jQuery 对固定元素的位置进行动画处理

javascript - 创建一个 onclick 处理程序,当单击其任何子元素时会触发该处理程序

html - div 不与另一个 div 居中

html - 在 CSS 中,我应该将字体大小更改应用到顶级元素还是最底层元素?

javascript - 如何在两个 div 之间的 contenteditable div 中设置插入符号/光标位置

javascript - 如何在 componentWillReceiveProps 上运行 Lottie 动画?

javascript - 从 typescript 代码滚动到元素( Angular 5)

javascript - 如何启动 react.js 的 nuka 轮播组件?