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


87

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

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

[...nodelist].filter

要么

Array.from(nodelist).filter

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


2
基本上,这两种方法都做相同的事情。您使用的是babel,然后[...coll]只需调用非Array.from(coll)的任何内容即可Array
Leonid Beschastny 2015年

FWIW,...较早的IDE可能不支持语法,而Array.from()这只是常规方法。
Marat Tanalin

Answers:


126
  • [...nodelist] 如果对象是可迭代的,则将由对象组成数组。
  • Array.from(nodelist)如果对象是可迭代的,或者对象是类似数组的对象(具有.length数字道具),则将从对象中组成一个数组

如果NodeList.prototype[Symbol.iterator]存在,您的两个示例将是相同的,因为这两种情况都涉及可迭代。如果您的环境尚未配置NodeList为可迭代,则第一个示例将失败,第二个示例将成功。Babel目前无法正确处理这种情况

所以如果你 NodeList是可迭代的,则取决于您所使用的。我可能会视情况选择。这样做的一个好处Array.from是,它需要一个映射函数的第二个参数,而第一个[...iterable].map(item => item)则必须创建一个临时数组,Array.from(iterable, item => item)而不必。但是,如果您不映射列表,则没关系。


17

TL; DR;

Array.prototype.slice.call(nodelist).filter

slice()方法返回一个数组。返回的数组是集合(NodeList)的浅表副本, 因此它比Array.from()更快地 工作,因此它与Array.from()一样快。

原始集合的元素被复制到返回的数组中,如下所示:

  • 对于对象引用(而不是实际对象),切片将对象引用复制到新数组中。原始数组和新数组都引用同一对象。如果引用的对象发生更改,则更改对新数组和原始数组均可见。
  • 对于字符串,数字和布尔值(不是字符串,数字和布尔对象),切片将值复制到新数组中。一个数组中的字符串,数字或布尔值的更改不会影响另一数组。

关于论点的简短解释

Array.prototype.slice(beginIndex,endIndex)

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

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

  • 将对象作为第一个参数。如果我们使用集合作为对象,则从字面上意味着我们直接从该对象的namespace调用slice方法。slice()

2
感谢您提供此代码段,它可能会提供一些有限的即时帮助。通过说明为什么这是一个很好的解决方案,正确的解释将大大提高其长期价值,对于其他存在类似问题的读者来说,这样做将更为有用。请编辑您的答案以添加一些解释,包括您所做的假设。
马克西米利安·彼得斯

我想知道是否没有IE支持Array.from。是时候找到IE机器了。现在我真的很困惑,因为我能够在IE10和IE11中使用Array.from:\。此方法在IE10 + 11中确实有效,但是当所有文档都另有说明时,Array.from无法使我轻松工作。
CTS_AE

Array.from在IE11中对我不起作用对象不支持属性或方法“ from”
Fus Ro Dah

谢谢,这为我工作在一个旧的JavaScript实现的
维克Seedoubleyew

1
Array.from还返回浅表副本。因此,我看不出您如何得出结论说它的运行速度比快Array#slice
罗伯特·

9

我找到了一个引用,它map直接在NodeList上使用

Array.prototype.map.call(nodelist, fn)

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


2

这个怎么样:

// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
  NodeList.prototype.filter = Array.prototype.filter;
}

// Use it like you'd expect:
const noClasses = document
  .querySelectorAll('div')
  .filter(div => div.classList.length === 0)

与MDN文档中针对NodeList.forEach(在“ Polyfill”下)提到的方法相同,适用于IE11,Edge,Chrome和FF。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.