很多JavaScript库(jQuery,Zepto)似乎在querySelectorAll(),getElementsByTag或ClassName结果上调用了Array.prototype.slice.call ......
通过在StackOverflow上阅读许多类似的问题/答案,我确实理解它将NodeList结果转换为真实数组,以便您可以在NodeLists上没有的结果上调用Array方法(slice,pop) - 但是我不明白的是为什么?你通常不需要在DOM节点列表上切片/弹出+ NodeLists已经有一个长度属性,所以无论如何它们都是可遍历的。
有些答案似乎暗示它是因为NodeList指向实时DOM对象。但是,如果将其转换为数组,引用仍然指向实时DOM节点 - 那么差异是什么?
或者是我完全错过的其他东西?它是否有助于Zepto / jQuery以某种方式缓存DOM元素的多个属性调用? (虽然我真的没看到,因为那些仍然是实时DOM引用)
答案 0 :(得分:2)
您通常不需要在DOM节点列表上进行切片/弹出
实际上,你这样做,这正是必要的原因。
例如,.eq()
,.first()
等的工作原理如何。 jQuery对象在数组中包含NodeList
的副本,然后各个方法接受该数组的切片。同样,您不能.add()
个节点到NodeList
。
此外,即使其中的元素随后从DOM中移除,这些数组也需要保持有效。数组中的引用仍然有效,可用于将这些元素重新插入DOM。
如果您拥有的只是一个实时NodeList
,那么元素会在从DOM中删除时自动从列表中消失,并且除非您单独引用它们,否则它们将永远丢失。
答案 1 :(得分:0)
...因为NodeList指向实时DOM对象......
不,这是一个误解。关键不在于列表中的每个节点都是“实时”DOM对象(真实但不相关),而是列表本身是“实时”。换句话说,只要DOM被更改,列表的内容就可以随时改变(甚至增长或缩小)。
如果您对列表中更改DOM的项目执行操作,则列表本身可能会在您使用它时动态更改。这意味着你的代码可能会陷入非常奇怪的递归和/或性能问题,而你却没有意识到这一点,也没有任何源代码中的任何指示。
将NodeList转换为常规Javascript数组会消除列表本身的“活跃度”,从而消除了自己射击的机会。