为什么无法在nodeList上调用forEach? [英] Why it is not possible to call forEach on a nodeList?
问题描述
我正在使用forEach遍历nodeList.我的代码如下
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);
});
此代码将引发错误
未捕获的TypeError:array.forEach不是函数
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);
}));
有人可以解释一下为什么无法在nodeList上调用forEach以及上面的第二段代码是做什么的.:)
Could someone please explain why it is not possible to call forEach on a nodeList and what does the above second code piece do. :)
修改: 2017年7月25日
此问题不适用于现代浏览器.您可以在其中的节点列表上使用forEach
This question does not valid for modern browsers. You can use forEach on node lists in them
尽管NodeList不是数组,但是可以对其进行迭代使用forEach().也可以使用以下命令将其转换为数组Array.from().
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().
但是,某些较旧的浏览器尚未实现NodeList.forEach()或Array.from().但是这些限制可以是通过使用Array.prototype.forEach()规避了(更多内容请参见文档).
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).
参考: MDN
推荐答案
这是JavaScript中的一项基本工作:您可以将一个函数从一个对象获取,然后 apply 应用于任何其他对象.也就是说:调用 this
并将其设置为应用函数所要应用的对象.这是可能的,因为在JavaScript中,所有属性名称等(显然)都是由名称标识的.因此,尽管 NodeList.length
与 Array.length
有所不同,但函数 Array.forEach
可以应用公开属性 length
(以及 forEach
所需的其他内容).
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()
返回类型为 NodeList 的对象,该对象恰巧暴露了length
属性,并且可以枚举(例如,可以通过以下方式访问它)[]
运算符); NodeList 不公开forEach
函数(如您在此处看到的那样:
querySelectorAll()
returns an object of type NodeList, which happens to exposelength
property and is enumerable (let's say it is accessible by[]
operator); NodeList does not exposeforEach
function (as you can see i.e here: https://developer.mozilla.org/en-US/docs/Web/API/NodeList) - that's why it's impossible to callforEach
directly on the results ofquerySelectorAll()
[].forEach
returns a function - this a not so clever shortcut forArray.prototype.forEach
- with
[].forEach.call(array, …)
this function is applied onto an object referenced byarray
, an object of type NodeList (that isforEach
is invoked witharray
asthis
in function body, so when insideforEach
there isthis.length
it refers tolength
inarray
despitearray
being NodeList and not real Array) - this works, because
forEach
is using properties that Array and NodeList have in common; it would fail if, i.e.forEach
wanted to use some property that Array has, but NodeList has not
这篇关于为什么无法在nodeList上调用forEach?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!