最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why it is not possible to call forEach on a nodeList? - Stack Overflow

programmeradmin3浏览0评论

I am using a forEach to loop through a nodeList. My code is as follows

var array = document.querySelectorAll('items');

array.forEach(function (item) {
    console.log(item);
}); 

And this code throws an error as

Uncaught TypeError: array.forEach is not a function

Then after reading few online blog articles i changed the code to this.

[].forEach.call(array, (function (item) {
    console.log(item);
})); 

Could someone please explain why it is not possible to call forEach on a nodeList and what does the above second code piece do. :)

Edit: 7/25/2017

This question does not valid for modern browsers. You can use forEach on node lists in them

Although NodeList is not an Array, it is possible to iterate on it using forEach(). It can also be converted to an Array using Array.from().

However some older browsers have not yet implemented NodeList.forEach() nor Array.from(). But those limitations can be circumvented by using Array.prototype.forEach() (more in this document).

Ref: MDN

I am using a forEach to loop through a nodeList. My code is as follows

var array = document.querySelectorAll('items');

array.forEach(function (item) {
    console.log(item);
}); 

And this code throws an error as

Uncaught TypeError: array.forEach is not a function

Then after reading few online blog articles i changed the code to this.

[].forEach.call(array, (function (item) {
    console.log(item);
})); 

Could someone please explain why it is not possible to call forEach on a nodeList and what does the above second code piece do. :)

Edit: 7/25/2017

This question does not valid for modern browsers. You can use forEach on node lists in them

Although NodeList is not an Array, it is possible to iterate on it using forEach(). It can also be converted to an Array using Array.from().

However some older browsers have not yet implemented NodeList.forEach() nor Array.from(). But those limitations can be circumvented by using Array.prototype.forEach() (more in this document).

Ref: MDN

Share Improve this question edited Jun 19, 2019 at 6:19 It worked yesterday. asked Jul 10, 2015 at 10:06 It worked yesterday.It worked yesterday. 4,61711 gold badges50 silver badges84 bronze badges 2
  • Check out NodeList.js – Edwin Reynoso Commented Aug 8, 2015 at 13:35
  • 1 Try this one line NodeList patch stackoverflow./a/32644632/502860 – iimos Commented Sep 19, 2015 at 11:24
Add a ment  | 

3 Answers 3

Reset to default 10

This is a fundamental thing in JavaScript: you can take a function from one object and apply to any other object. That is: call it with this set to the object you apply the function to. It is possible, because in JavaScript all property names etc. are (plainly speaking) identified by name. So despite NodeList.length being something different then Array.length the function Array.forEach can be applied to anything that exposes property length (and other stuff that forEach requires).

So what happens in your case is that:

  • querySelectorAll() returns an object of type NodeList, which happens to expose length property and is enumerable (let's say it is accessible by [] operator); NodeList does not expose forEach function (as you can see i.e here: https://developer.mozilla/en-US/docs/Web/API/NodeList) - that's why it's impossible to call forEach directly on the results of querySelectorAll()
  • [].forEach returns a function - this a not so clever shortcut for Array.prototype.forEach
  • with [].forEach.call(array, …) this function is applied onto an object referenced by array, an object of type NodeList (that is forEach is invoked with array as this in function body, so when inside forEach there is this.length it refers to length in array despite array being NodeList and not real Array)
  • this works, because forEach is using properties that Array and NodeList have in mon; it would fail if, i.e. forEach wanted to use some property that Array has, but NodeList has not

the NodeList object doesnt contain the method forEach, its a method of the Array object. the below code:

[].forEach.call(array, (function (item) {
    console.log(item);
})); 

is using the forEach method from array and passing it a NodeList.

Another option you have, and arguabiliy better, is to convert your NodeList into an array, like this:

var myArrayOfNodes = [].slice.call(NodeList);

This uses the Array objects slice method to create an array of nodes from a NodeList. This is a better aproach as you can then use an array rather then hacking an array-like object

querySelectorAll gets the element in array-like object not an Array. So you need to use as you have in second code example.

发布评论

评论列表(0)

  1. 暂无评论