DOM对象的Javascript集合-为什么我不能使用Array.reverse()进行反转?
如下面的代码所示,反转DOM对象数组可能是什么问题:
var imagesArr = new Array(); imagesArr = document.getElementById("myDivHolderId").getElementsByTagName("img"); imagesArr.reverse();
在Firefox 3中,当我调用reverse()
方法时,脚本停止执行,并在Web Developer Toolbar的控制台中显示以下错误:
imagesArr.reverse is not a function
可以使用for循环迭代imagesArr
变量,并且可以访问诸如imagesArr [i]
之类的元素,那么为什么在调用reverse()
方法时不将其视为数组?
解决方案
回答
第一行是无关紧要的,因为它不会强制分配给该变量,因此javascript可以采用另一种方式。 imagesArr的类型不是Array(),无论getElementsByTagName(" img")的返回类型是什么。在这种情况下,它是Firefox 3中的HtmlCollection。
此对象上唯一的方法是索引器和长度。为了反向工作,只需向后迭代。
回答
因为getElementsByTag名称实际上返回NodeList结构。为了语法上的方便,它具有类似于索引属性的数组,但它不是数组。例如,如果在myDivHolderId下添加新的img标记,则该条目集实际上会不断地动态更新,它将自动出现在imagesArr中。
有关更多信息,请参见http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177.
回答
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);