17

反转 DOM 对象数组可能会出现什么问题,如下面的代码所示:

var imagesArr = new Array();
imagesArr = document.getElementById("myDivHolderId").getElementsByTagName("img");
imagesArr.reverse();

在 Firefox 3 中,当我调用该reverse()方法时,脚本停止执行并在 Web 开发人员工具栏的控制台中显示以下错误:

imagesArr.reverse is not a function

imagesArr变量可以通过for循环进行迭代,并且可以访问类似的元素,那么为什么在调用方法imagesArr[i]时不将其视为数组呢?reverse()

4

6 回答 6

16

因为 getElementsByTag 名称实际上返回了一个 NodeList 结构。为了语法方便,它具有类似数组的索引属性,但它不是数组。例如,条目集实际上是在不断地动态更新的——如果在 myDivHolderId 下添加新的 img 标签,它会自动出现在 imagesArr 中。

有关更多信息,请参阅http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177

于 2008-09-05T12:17:39.777 回答
10

getElementsByTag()返回 NodeList 而不是 Array。您可以将 NodeList 转换为 Array,但请注意该数组将是另一个对象,因此反转它不会影响 DOM 节点的位置。

var listNodes = document.getElementById("myDivHolderId").getElementsByTagName("img");
var arrayNodes = Array.slice.call(listNodes, 0);
arrayNodes.reverse();

为了更改位置,您必须删除 DOM 节点并在正确的位置再次添加它们。

Array.prototype.slice.call(arrayLike, 0)是一种将类数组转换为数组的好方法,但如果您使用的是 JavaScript 库,它实际上可能提供了一种更好/更快的方法。例如,jQuery 有$.makeArray(arrayLike).

您还可以直接在 NodeList 上使用 Array 方法:

Array.prototype.reverse.call(listNodes);
于 2008-09-05T13:04:30.087 回答
5

getElementsByTag()返回 NodeList 而不是 Array。您需要将 NodeList 转换为数组,然后将其反转。

var imagesArr = [].slice.call(document.getElementById("myDivHolderId").getElementsByTagName("img"), 0).reverse();
于 2015-01-29T10:01:29.687 回答
4

这个问题实际上可以用数组扩展运算符轻松解决。

let elements = document.querySelectorAll('button');
elements = [...elements];
console.log(elements) // Before reverse
elements = elements.reverse();  // Now the reverse function will work
console.log(elements)  // After reverse
<html>
<body>
<button>button1</button>
<button>button2</button>
<button>button3</button>
<button>button4</button>
<button>button5</button>
</body>
</html>

于 2021-06-21T07:47:24.543 回答
3

我知道这个问题很老,但我认为它需要一点澄清,因为这里的一些答案已经过时,因为 W3C 改变了定义,因此这些方法的返回值getElementsByTagName()getElementsByClassName()

在撰写此答案时,这些方法返回一个类型为非HTMLCollection空或非空的对象。 NodeList

children这就像返回类型对象的属性之间的区别,HTMLCollection因为它仅由元素组成,不包括文本或注释节点,childNodes而返回类型对象,NodeList因为它也可以包含其他节点类型,如文本和注释。

注意:我会在这里切题并表达我对为什么querySelectorAll()方法当前返回 aNodeList而不是a 缺乏洞察力,HTMLCollection因为它仅适用于文档中的元素节点,没有别的。

可能这与未来其他节点类型的潜在覆盖有关,他们寻求更面向未来的解决方案,谁知道呢?:)

编辑:我认为我得到了选择 a而NodeList不是HTMLCollection.querySelectorAll()

由于他们构建HTMLCollection为完全且完全实时的,并且由于此方法不需要此实时功能,因此他们决定采用一种NodeList实现方式,以经济高效地最好地服务于其目的。

于 2015-03-20T14:00:17.547 回答
1

您的第一行是无关紧要的,因为它不会强制分配给变量,javascript 以另一种方式工作。imagesArr 不是 Array() 类型,无论 getElementsByTagName("img") 的返回类型是什么。在这种情况下,它是 Firefox 3 中的 HtmlCollection。

此对象的唯一方法是索引器和长度。为了反向工作,只需向后迭代。

于 2008-09-05T12:16:42.933 回答