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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32765157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:11:05  来源:igfitidea点击:

Filter or map nodelists in ES6

javascriptarraysfilterecmascript-6nodelist

提问by Christophe

What is the most efficient way to filter or map a nodelist in ES6?

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

Based on my readings, I would use one of the following options:

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

[...nodelist].filter

or

或者

Array.from(nodelist).filter

Which one would you recommend? And are there better ways, for example without involving arrays?

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

回答by loganfsmyth

  • [...nodelist]will make an array of out of an object if the object is iterable.
  • Array.from(nodelist)will make an array out of an object if the object is iterable orif the object is array-like (has .lengthand numeric props)
  • [...nodelist]如果对象是可迭代的,则会从对象中创建一个数组。
  • Array.from(nodelist)如果对象是可迭代的或者对象是类似数组的(具有.length和数字道具),将从对象中创建一个数组

Your two examples will be identical if NodeList.prototype[Symbol.iterator]exists, because both cases cover iterables. If your environment has not been configured such that NodeListis iterable however, your first example will fail, and the second will succeed. Babelcurrently does not handle this case properly.

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

So if your NodeListis iterable, it is really up to you which you use. I would likely choose on a case-by-case basis. One benefit of Array.fromis that it takes a second argument of a mapping function, whereas the first [...iterable].map(item => item)would have to create a temporary array, Array.from(iterable, item => item)would not. If you are not mapping the list however, it does not matter.

因此,如果您NodeList是可迭代的,则完全取决于您使用哪个。我可能会根据具体情况进行选择。一个好处Array.from是它需要映射函数的第二个参数,而第一个[...iterable].map(item => item)必须创建一个临时数组,Array.from(iterable, item => item)而不会。但是,如果您没有映射列表,则没有关系。

回答by Serge Seletskyy

TL;DR;

TL; 博士;

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

The slice() method returns an array. That returned array is a shallow copy of collection (NodeList) So it works faster than **Array.from()**

slice() 方法返回一个数组。返回的数组是集合 (NodeList) 的浅拷贝, 因此它比 **Array.from()** 工作得更快

Elements of the original collection are copied into the returned array as follows:

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

  • For object references (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.
  • For strings, numbers and booleans (not String, Number and Boolean objects), slice copies the values into the new array. Changes to the string, number or boolean in one array do not affect the other array.
  • 对于对象引用(而不是实际对象),切片将对象引用复制到新数组中。原始数组和新数组都指向同一个对象。如果引用的对象发生更改,则更改对新数组和原始数组都可见。
  • 对于字符串、数字和布尔值(不是字符串、数字和布尔对象),切片将值复制到新数组中。对一个数组中的字符串、数字或布尔值的更改不会影响另一个数组。

Short explanation regarding arguments

关于论点的简短解释

Array.prototype.slice(beginIndex, endIndex)

Array.prototype.slice(beginIndex, endIndex)

  • takes optional args beginIndex and endIndex. If they are not provided slices uses beginIndex == 0, thus it extracts all the items from the collection
  • 采用可选参数 beginIndex 和 endIndex。如果没有提供切片,则使用 beginIndex == 0,因此它从集合中提取所有项目

Array.prototype.slice.call(namespace, beginIndex, endIndex)

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

  • takes an object as the first argument. If we use a collection as an object it literally means that we call slice method directly from that object namespace.slice()
  • 将一个对象作为第一个参数。如果我们使用一个集合作为一个对象,它的字面意思是我们直接从该对象的namespace.slice()调用 slice 方法

回答by goweon

I found a referencethat uses mapdirectly on the NodeList by

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

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

I haven't tested it, but it seems plausible that this would be faster because it should access the NodeList directly.

我还没有测试过它,但是这看起来可能会更快,因为它应该直接访问 NodeList。

回答by panepeter

How about this:

这个怎么样:

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

It's the same approach as mentioned in the MDN docs for NodeList.forEach(under 'Polyfill'), it works for IE11, Edge, Chrome and FF.

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