在 ES6中筛选或映射节点列表

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

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

[...nodelist].filter

或者

Array.from(nodelist).filter

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

96046 次浏览
  • 如果对象是可迭代的,[...nodelist]将从对象中生成一个数组。
  • 如果对象是可迭代的,如果对象是类似于数组的(具有 .length和数值道具) ,则 Array.from(nodelist)将从对象中创建一个数组

如果存在 NodeList.prototype[Symbol.iterator],那么您的两个示例将是相同的,因为两种情况都涵盖了可迭代文件。但是,如果您的环境没有配置成 NodeList是可迭代的,那么您的第一个示例将会失败,而第二个示例将会成功。目前为 Babel

因此,如果您的 NodeList是可迭代的,那么您使用哪个 NodeList实际上取决于您自己。我可能会根据具体情况来选择。Array.from的一个好处是它接受映射函数的第二个参数,而第一个 [...iterable].map(item => item)必须创建一个临时数组,而 Array.from(iterable, item => item)不需要。但是,如果您没有映射该列表,那么这并不重要。

;

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

Slice ()方法返回一个数组。 返回的数组是集合的浅表副本(NodeList) 所以它比 数组来自()运行得更快 所以它的工作速度和 < strong > Array.from ()一样快

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

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

关于争论的简短解释

Slice (开始索引,结束索引)

  • 采用可选的 args 开始索引和结束索引。 如果没有为它们提供切片,则切片使用 BegIndex = = 0,因此它将从集合中提取所有项

Slice.call (名称空间,开始索引,结束索引)

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

我发现一个 参考文献直接在 NodeList 上使用 map

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

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

这样吧:

// 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)

它与 NodeList.foreach 的 MDN 文档中提到的方法相同(在‘ Polyfill’下) ,它是 为 IE11工作、 Edge、 Chrome 和 FF。

在 ES6中筛选或映射节点列表

我从这个简单的函数出来

function filterNodeList(NodeList, callback) {
if (typeof callback !== "function") callback = (i) => i; // Any have better idear?


const Result = document.createElement("div");
//# No need to filter empty NodeList
if (NodeList.length === 0) return NodeList;


for (let i = 0; i < NodeList.length; i++) {
if (callback(NodeList.item(i))) Result.appendChild(NodeList.item(i));
}


return Result.childNodes;}

我愿意学习更多: >

[...a].filter vs Array.from(a).filter

在性能上没有“真正的”差异,Array.from可能会快一点点,因为您没有在“ JS 级别”上创建新的 Array,而是直接在本机代码中创建。

性能——考虑使用 都不是没有

但是对于 表演(也要避免“ Array-ing”) ,你应该考虑 为什么是否过滤了 NodeList在哪里? 怎么做。在许多情况下,您只需要使用 idclass或其他 CSS 选择器来选择特定的元素。

document.querySelectorAll类似于 快10-200倍,适用于任何 CSS 选择器
document.getElementById甚至更快(当然需要 id)

你甚至可以优化 querySelectorAll或绕过“未知”的情况下,如果你提供了一个预先存储的父进行查看,让我给你一个例子:

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

快了将近10倍

Array.from(a).filter(el => el.classList.contains("flex--item"))

还要注意,document.querySelectorAll('#mainbar .flex--item');仍然比 Array过滤快约5倍,但比使用 id预存储父节点慢约2倍。

除了更好的性能,您的 也将总是得到 NodeList(它可能是空的,但它仍将是 NodeList) ,这适用于 document.querySelectorAll()Element.querySelectorAll()

使用 ECMAS 2016:

let nodes = [...document.querySelector('__SELECTOR__').childNodes].filter(item => item.nodeType === 1);