在 ES6 中过滤或映射节点列表

问题描述 投票:0回答:7

在 ES6 中过滤或映射节点列表最有效的方法是什么?

根据我的阅读,我会使用以下选项之一:

[...nodelist].filter

Array.from(nodelist).filter

您会推荐哪一款?有没有更好的方法,例如不涉及数组?

javascript arrays filter ecmascript-6 nodelist
7个回答
261
投票
    如果对象是可迭代的,
  • [...nodelist]
    将从对象中创建一个数组。
  • 如果对象是可迭代的,
  • Array.from(nodelist)
    将从对象中创建一个数组或者如果对象是类似数组的(具有
    .length
    和数字属性)
如果

NodeList.prototype[Symbol.iterator]

 存在,那么您的两个示例将是相同的,因为这两种情况都涵盖了可迭代对象。但是,如果您的环境尚未配置为可迭代,则您的第一个示例将失败,而第二个示例将成功。 
NodeList
目前
无法妥善处理此案
因此,如果您的 Babel

是可迭代的,那么这实际上取决于您使用哪个。我可能会根据具体情况进行选择。

NodeList

 的一个好处是它需要映射函数的第二个参数,而第一个 
Array.from
 必须创建一个临时数组,而 
[...iterable].map(item => item)
 则不需要。但是,如果您没有映射列表,也没关系。

我发现了一个

24
投票
直接在 NodeList 上使用

Array.from(iterable, item => item) by

map

我还没有测试过它,但似乎这会更快,因为它应该直接访问 NodeList。
    

TL;博士;

21
投票
Array.prototype.map.call(nodelist, fn)

slice() 方法返回一个数组。 返回的数组是集合(NodeList)的浅表副本
所以它比 
Array.from()

运行得更快 所以它的工作速度和 Array.from() 一样快 原始集合的元素被复制到返回的数组中,如下所示:

对于对象引用(而不是实际对象),切片会将对象引用复制到新数组中。原始数组和新数组都引用同一个对象。如果引用的对象发生更改,则新数组和原始数组都可以看到这些更改。

    对于字符串、数字和布尔值(不是字符串、数字和布尔对象),slice 将值复制到新数组中。对一个数组中的字符串、数字或布尔值的更改不会影响另一个数组。
  • 有关论点的简短解释

Array.prototype.slice(beginIndex, endIndex)

采用可选参数 beginIndex 和 endIndex。 如果未提供切片,则使用 beginIndex == 0,因此它会从集合中提取所有项目

  • Array.prototype.slice.call(命名空间,beginIndex,endIndex)

将一个对象作为第一个参数。如果我们使用集合作为对象,它的字面意思是我们直接从该对象调用 slice 方法

namespace.slice()

9
投票
vs

[...a].filter

性能上没有“真正”的差异,
Array.from(a).filter

可能会快一点,因为您没有在“JS级别”创建新的

Array.from

,但它直接发生在本机代码中。
性能 - 考虑

使用

任一 但是,为了性能

(也为了避免“

Array-ing”),您应该考虑为什么

要过滤
Array以及在哪里/如何
获得它。在许多情况下,您只需要通过 
NodeListid
 或其他 CSS 选择器来获得特定元素。
class

就像

10 倍 - 200 倍快

 并且适用于任何 CSS 选择器
document.querySelectorAll甚至更快(但当然需要
document.getElementById
如果您提供预先存储的父级来查看,您甚至可以优化
id

或绕过“未知”情况,让我给您举个例子:

querySelectorAll

几乎比

快 10 倍 let mainbar = document.getElementById('mainbar'); mainbar.querySelectorAll('.flex--item');

另请注意,
Array.from(a).filter(el => el.classList.contains("flex--item"))
仍比

document.querySelectorAll('#mainbar .flex--item');

 过滤快约 5 倍,但比使用 
Array
 预存储父级慢约 2 倍。
除了更好的性能之外,您
还将始终获得

id

(它可能是空的,但它仍然是
NodeList
),这对于
NodeList
document.querySelectorAll()
都适用
    

这个怎么样:

7
投票
Element.querySelectorAll()

这与
NodeList.forEach 的 MDN 文档(在“Polyfill”下)中提到的方法相同,它
适用于 IE11

、Edge、Chrome 和 FF。



0
投票

© www.soinside.com 2019 - 2024. All rights reserved.