是否可以在不循环的情况下在其父节点中获取元素的数字索引?

IT技术 javascript dom
2021-03-08 08:34:53

通常我是这样做的:

for(i=0;i<elem.parentNode.length;i++) {
  if (elem.parentNode[i] == elem) //.... etc.. etc...
}
6个回答
function getChildIndex(node) {
  return Array.prototype.indexOf.call(node.parentNode.childNodes, node);
}

这似乎适用于 Opera 11、Firefox 4、Chromium 10。其他浏览器未经测试。如果节点没有父节点,它将抛出 TypeError (node.parentNode !== undefined如果您关心这种情况,请添加检查)。

当然,Array.prototype.indexOfdoes 仍然循环,只是在函数调用中。没有循环就不可能做到这一点。


注意:如果要获取子节点的索引Element,可以将上面的函数修改childNodeschildren

function getChildElementIndex(node) {
  return Array.prototype.indexOf.call(node.parentNode.children, node);
}
请注意 parentNode.childNodes 可能包含text节点,您可能不希望它们被考虑在内。
2021-04-24 08:34:53
@JonathanPotter不清楚问题在问什么,因为它的代码不起作用,无论是想要第n个子元素还是第n个子节点
2021-04-30 08:34:53
应该.children代替.childNodes.
2021-05-02 08:34:53
indexOf确实扫描了整个阵列,所以从技术上讲它并没有真正回答这个问题。但由于 indexOf 是一个内置函数,它会比编写自己的循环运行得更快。
2021-05-08 08:34:53
不错,简短但请注意,它不适用于 IE < 9。通常不鼓励Array.prototype宿主对象应用方法,因为规范不能保证它们会正常工作:“indexOf 函数是否可以成功应用于宿主对象是依赖于实现的。”
2021-05-14 08:34:53

您可以计算兄弟姐妹... childNodes 列表包括文本元素节点-

function whichChild(elem){
    var  i= 0;
    while((elem=elem.previousSibling)!=null) ++i;
    return i;
}
对于大多数节点”是否曾经有一个元素可以有多个 parentNode 的实例?
2021-04-21 08:34:53
为避免计算子列表中的空格,请改用 previousElementSibling
2021-04-29 08:34:53
惊人的!- 一个非常优雅的解决方案
2021-05-03 08:34:53

选项1

您可以使用该Array.from()方法将一个HTMLCollectionof 元素转换为一个数组。从那里,您可以使用本机.indexOf()方法来获取索引:

function getElementIndex (element) {
  return Array.from(element.parentNode.children).indexOf(element);
}

如果您想要节点索引(与元素索引相反),则将children属性替换childNodes属性

function getNodeIndex (element) {
  return Array.from(element.parentNode.childNodes).indexOf(element);
}

选项#2

您可以使用该.call()方法来调用数组类型的本机.indexOf()方法。如果您查看源代码,这就是该.index()方法在 jQuery 中的实现方式。

function getElementIndex(element) {
  return [].indexOf.call(element.parentNode.children, element);
}

同样,使用childNodes属性代替children属性:

function getNodeIndex (element) {
  return [].indexOf.call(element.parentNode.childNodes, element);
}

选项#3

您还可以使用扩展运算符

function getElementIndex (element) {
  return [...element.parentNode.children].indexOf(element);
}
function getNodeIndex (element) {
  return [...element.parentNode.childNodes].indexOf(element);
}
此处的选项 #1 是此页面上列出的唯一对我有用的选项。
2021-05-01 08:34:53

如果不以某种方式循环,则无法在其父节点中获取节点的索引,无论是 - 循环,还是or 之forArray方法,或其他方式。DOM 中的索引操作是线性时间的,而不是恒定时间的。indexOfforEach

更一般地说,如果列表突变是可能的(并且 DOM 肯定支持突变),则通常不可能提供以恒定时间运行的索引操作。有两种常见的实现策略:链表(通常是双重的)和数组。使用链表查找索引需要走一段路。使用数组查找索引需要扫描。一些引擎会缓存索引以减少计算所需的时间node.childNodes[i],但是如果您正在搜索节点,这对您没有帮助。不问问题是最好的策略。

我想你已经明白了,但是:

  • 确保变量“i”声明为 var
  • 在比较中使用===而不是==
...因为未与var对象一起声明或附加到对象的变量位于全局对象 ( window) 上,并且==对于具有不可预测(但有据可查且疯狂的)含义的“某种相等”值返回 true。
2021-04-18 08:34:53