循环遍历NodeList:Array.prototype.forEach.call()vs Array.from()。forEach

时间:2017-04-17 10:47:13

标签: javascript arrays foreach prototype nodelist

所以我想要一种简单的方法来循环遍历节点列表,我总是讨厌我不能在节点列表上使用forEach

所以,现在我做:Array.prototype.forEach.call(nodeList, callback)

对于索引,我这样做:Array.prototype.indexOf.call(nodeList, node)

对于我在nodeLists上使用Array.prototype的几乎所有内容。

但我想知道这些是否被视为黑客攻击?

他们是正确的做法吗?

另外,假设我实际上并不需要来自nodeList的数组,那么使用Array.from(nodeList).forEach(callback)是否有优势呢?

3 个答案:

答案 0 :(得分:3)

Array.prototype.forEach.call(nodeList, callback)将在节点列表中应用forEach的逻辑。 forEach只有一个for循环,从索引0this.length并在每个项目上调用回调。此方法调用forEach将节点列表作为其this值传递,因为节点列表具有类似的数组属性(length01, ...),一切正常。

Array.from(nodeList).forEach(callback)将从节点列表创建一个新数组,然后在该新数组上使用forEach。第二种方法可以分为两个自解释线:

var newArray = Array.from(nodeList);  // create a new array out of the node list
newArray.forEach(callback);           // call forEach on the new array

第一种方法更好,因为它不会创建额外的不需要的资源,而且它可以直接在节点列表上工作。

答案 1 :(得分:3)

第一种方法是ES5兼容:

Array.prototype.forEach.call(nodeList, callback).

第二种方法使用仅在ES6中定义的Array.from

Array.from(nodeList).forEach(callback)

但是,您没有在此优化Array.from的使用,因为您首先创建整个数组,然后使用forEach进行迭代。

而是使用Array.from的第二个参数:

Array.from(nodeList, callback)

现在整个操作都在一次迭代中发生。

好处是在上面的表达式中,回调用作映射函数,因此如果它返回一个值,则整个表达式返回由这些返回值定义的数组。但使用它当然是可选的。例如,您可以创建一个包含节点文本内容的数组,如下所示:

texts = Array.from(nodeList, node => node.textContent)

答案 2 :(得分:2)

var array=Array.from(nodeList);
//after some time
var array2=Array.from(nodeList);

如果比较这些阵列,你会发现它们不一定相等。 NodeLists反映了DOM的变化,当你复制它们时,数组保持静态。如果你想要这种行为/不关心你很好。但是 Array.from 是相当新的,因此它不被旧版浏览器所理解,所以它不应该在生产环境中使用(如果你不像Babel那样使用它)。