admin管理员组

文章数量:1290191

So I want an easy way to loop through nodelists, and I always hated that I can't use forEach on nodeLists.

So, now I do: Array.prototype.forEach.call(nodeList, callback).

and for index, i do: Array.prototype.indexOf.call(nodeList, node).

and for pretty much everything I use Array.prototype on nodeLists.

But I'm wondering if these are considered hacks?

Are they the right way to do it?

Also, assuming I don't actually need an array from nodeList, is there an advantage of using Array.from(nodeList).forEach(callback) instead?

So I want an easy way to loop through nodelists, and I always hated that I can't use forEach on nodeLists.

So, now I do: Array.prototype.forEach.call(nodeList, callback).

and for index, i do: Array.prototype.indexOf.call(nodeList, node).

and for pretty much everything I use Array.prototype on nodeLists.

But I'm wondering if these are considered hacks?

Are they the right way to do it?

Also, assuming I don't actually need an array from nodeList, is there an advantage of using Array.from(nodeList).forEach(callback) instead?

Share Improve this question asked Apr 17, 2017 at 10:47 BigNameBigName 1,0972 gold badges17 silver badges29 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

Array.prototype.forEach.call(nodeList, callback) will apply the logic of forEach on the node list. forEach just have a for loop in it that goes from index 0 to this.length and calling a callback on each of the items. This method is calling forEach passing the node list as its this value, since node lists have similar properties of an array (length and 0, 1, ...), everything works fine.

Array.from(nodeList).forEach(callback) will create a new array from the node list, then use forEach on that new array. This second method could be split into two self explanatory lines:

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

The first approach is better because it doesn't create additional uneeded resources and it work on node lists directly.

The first method is ES5 patible:

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

The second method uses Array.from which was only defined in ES6:

Array.from(nodeList).forEach(callback)

However, you are not optimising the use of Array.from here, because you first create the whole array, and then iterate over it with forEach.

Instead use the second argument of Array.from:

Array.from(nodeList, callback)

Now the whole operation happens in one iteration.

The nice thing is that in the above expression, the callback is used as a mapping function, so if it returns a value, the whole expression returns the array as defined by those return values. But using this is of course optional. For instance, you could create an array with the text contents of the nodes like this:

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

Warning

If you use Array.from with callback, and the node list is a live node list (see NodeList), and you mutate the node list in the callback, then this can have undesired effects. In that case use the two step method where you first turn the node list into an array, and only then perform the callback on its entries.

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

If you pare these Arrays youll see that they are not necessarily equal. NodeLists reflect the change of the DOM, as you copy them the arrays stay static. If you want this behaviour / dont care about youre fine. However Array.from is quite new, therefore it isnt understood by older browsers, so it shouldnt be used in productional environments ( if youre not using sth like Babel).

本文标签: javascriptLoop through NodeList ArrayprototypeforEachcall() vs Arrayfrom()forEachStack Overflow