我刚刚通过电子API演示代码示例突然出现了一个狂野的表达 - 这对我来说是完全陌生的 - 出现了:
const links = document.querySelectorAll('a[href]');
Array.prototype.forEach.call(links, function (link) {
// WWIII here
})
我明白这段代码正在做什么,但我习惯了这样的语法:
links.forEach(function (links) {});
那两者究竟有什么区别?我已经阅读了有关此主题的各种StackOverflow线程,但它们要么含糊不清要么根本不回答这个问题。有人说它有类似于数组的集合,不能被.forEach()迭代,而不是Array.prototype.forEach.call()。这是过度繁琐和长版本的唯一优势吗?
提前致谢!
答案 0 :(得分:23)
prototype
中的“类方法”。这意味着即使对象不从the Array
prototype继承,也可以在其上调用Array
方法,只要它遵循数组结构(即:它是一个{{1}的对象。由整数索引的属性和属性)。但是,该对象不引用length
,因此您需要明确选择Array.prototype
作为方法所在的对象。
document.querySelectorAll
函数返回NodeList
,它既不是Array.prototype
也不是Array
原型的继承。但是,由于Array
具有与NodeList
类似的内部结构,您仍然可以使用Array
函数。但由于forEach
未继承NodeList
原型,因此尝试在Array
上使用.forEach
会引发错误(这不是完全是的 - 请参阅我的答案末尾的注释。出于这个原因,您需要明确声明您正在NodeList
上Array.prototype
调用方法,并且使用the .call
method from Function.prototype
来完成。
总结:
NodeList
表示:
从Array.prototype.forEach.call(links, function(link) { /* something */ })
获取forEach
函数并在Array.prototype
上调用它,这是一个非links
对象,并以某个函数作为参数。
请注意,在最新版本的浏览器中,Array
原型 提供a forEach
method,其工作方式与NodeList
相同,因此示例来自Electron API可能使用Array
版本与旧版本兼容。如果您有一个网络应用程序并且只关心支持现代版Chrome和Firefox,那么您只需拨打Array
上的forEach
即可。实际上,从Electron updates about 2 weeks after whenever Chrome updates开始,在Electron中使用NodeList
应该是安全的。 :)
答案 1 :(得分:3)
这是一个有趣的问题。半年前我会说link.forEach
不是关于缩短语法,但它实际上不应该起作用。然后我会解释这意味着许多数组方法故意泛型,这意味着它们的内部实现只考虑this
对象的数字索引和长度属性,但不是关心它是数组实例。基本上@Pedro Castilho在他的回答中说道。
但是,现在我要说现在常绿浏览器(除了IE11,Edge,截至2017年4月)已经实现了NodeList.prototype.forEach便捷方法,因此您不再需要使用.call
hack或{{ 1}}以便用Array.from
迭代NodeList。
所以我的摘要:如果您不需要支持IE,请使用forEach
而不是NodeList.prototype.forEach
。它在内部可能是相同的,但在概念上更清洁。如果您确实需要支持IE,并且您不想再添加一个pollyfill,请使用Array.prototype.forEach
或更好Array.prototype.call
。
答案 2 :(得分:2)
这可能与document.querySelectorAll
返回a static NodeList
而不是an Array
的方式有关。
使用Array
的原型,您仍然可以拨打forEach
,它类似于operating on arguments。