[].forEach.call()在JavaScript中做什么?
我查看了一些代码片段,发现多个元素在节点列表上调用函数,并将forEach应用于空数组 例如,我有一些类似于:[].forEach.call()在JavaScript中做什么?,javascript,arrays,foreach,ecmascript-5,nodelist,Javascript,Arrays,Foreach,Ecmascript 5,Nodelist,我查看了一些代码片段,发现多个元素在节点列表上调用函数,并将forEach应用于空数组 例如,我有一些类似于: [].forEach.call( document.querySelectorAll('a'), function(el) { // whatever with the current node }); 但我不明白它是怎么工作的。有人能给我解释一下forEach前面的空数组的行为以及调用如何工作吗?空数组的原型中有一个属性forEach,它是一个函数对象。(空数组只是获取所有a
[].forEach.call( document.querySelectorAll('a'), function(el) {
// whatever with the current node
});
但我不明白它是怎么工作的。有人能给我解释一下forEach前面的空数组的行为以及
调用如何工作吗?空数组的原型中有一个属性forEach
,它是一个函数对象。(空数组只是获取所有array
对象都具有的forEach
函数引用的一种简单方法。)函数对象反过来又具有一个call
属性,该属性也是一个函数。调用函数的调用
函数时,它使用给定参数运行函数。第一个参数在被调用函数中变为this
您可以找到调用
函数的文档。forEach
的文档是。空数组的原型中有一个属性forEach
,它是一个函数对象。(空数组只是获取所有array
对象都具有的forEach
函数引用的一种简单方法。)函数对象反过来又具有一个call
属性,该属性也是一个函数。调用函数的调用
函数时,它使用给定参数运行函数。第一个参数在被调用函数中变为this
您可以找到调用
函数的文档。forEach
的文档是。返回一个节点列表
,它类似于一个数组,但不完全是一个数组。因此,它没有forEach
方法(数组对象通过array.prototype
继承)
由于NodeList
类似于数组,数组方法实际上会对其起作用,因此通过使用[].forEach.call
可以在NodeList
的上下文中调用array.prototype.forEach
方法,就好像您能够简单地执行您的NodeList.forEach(/*…*/)
请注意,空数组文字只是扩展版本的快捷方式,您可能也会经常看到:
Array.prototype.forEach.call(/*...*/);
返回一个节点列表
,它类似于一个数组,但不完全是一个数组。因此,它没有forEach
方法(数组对象通过array.prototype
继承)
由于NodeList
类似于数组,数组方法实际上会对其起作用,因此通过使用[].forEach.call
可以在NodeList
的上下文中调用array.prototype.forEach
方法,就好像您能够简单地执行您的NodeList.forEach(/*…*/)
请注意,空数组文字只是扩展版本的快捷方式,您可能也会经常看到:
Array.prototype.forEach.call(/*...*/);
它可以更好地使用
Array.prototype.forEach.call( document.querySelectorAll('a'), function(el) {
});
is所做的是document.querySelectorAll('a')
返回一个类似于数组的对象,但它不从数组
类型继承。
因此,我们从数组.prototype
对象调用forEach
方法,上下文作为文档返回的值。querySelectorAll('a')
使用
Array.prototype.forEach.call( document.querySelectorAll('a'), function(el) {
});
is所做的是document.querySelectorAll('a')
返回一个类似于数组的对象,但它不从数组
类型继承。
因此,我们从数组调用forEach
方法。prototype
对象的上下文是文档返回的值。querySelectorAll('a')
[]
是一个数组。
这个数组根本不用
它被放在页面上,因为使用数组可以访问数组原型,比如.forEach
这比键入Array.prototype.forEach.call(…)要快得多代码>
接下来,forEach
是一个将函数作为输入的函数
[1,2,3].forEach(function (num) { console.log(num); });
…对于this
中的每个元素(其中this
类似于数组,因为它具有长度
,您可以访问它的部分,如this[1]
),它将传递三个信息:
数组中的元素
元素的索引(第三个元素将通过2
)
对数组的引用
最后,.call
是函数拥有的原型(它是在其他函数上被调用的函数)。
.call
将取其第一个参数,并用您传递的call
替换常规函数中的此
,作为第一个参数(未定义的
或空
将在日常JS中使用窗口
,或是您传递的任何内容,如果处于“严格模式”)。其余参数将传递给原始函数
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
因此,您正在创建一种调用forEach
函数的快速方法,并且您正在将此
从空数组更改为所有
标记的列表,并且对于每个
按顺序调用提供的函数
编辑
逻辑结论/清理
下面是一篇文章的链接,建议我们放弃函数式编程的尝试,每次都坚持手动、内联循环,因为这种解决方案既有黑客味又难看
我要说的是,虽然.forEach
不如它的对应物,.map(transformer)
,.filter(predicate)
,.reduce(combiner,initialValue)
,但当您真正想做的只是修改外部世界(而不是数组)n次,同时可以访问arr[I]
或i
那么,我们如何处理这种差异呢?因为格言显然是一个才华横溢、学识渊博的人,我想说一句
function countArgs (...allArgs) {
return allArgs.length;
}
function logArgs (...allArgs) {
return allArgs.forEach(arg => console.log(arg));
}
function extend (subject, ...others) { /* return ... */ }
var nodeArray = [ ...nodeList1, ...nodeList2 ];
function forEach( list, callback ) {
Array.prototype.forEach.call( list, callback );
}
forEach( document.querySelectorAll('a'), function( el ) {
// whatever with the current node
});
NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;
document.querySelectorAll('a').forEach(function(el) {
// whatever with the current node
});
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
}
const forEach = (array, callback) => {
if (!array || !array.length || !callback) return
for (var i = 0; i < array.length; i++) {
callback(array[i], i);
}
}
forEach(document.querySelectorAll('.a-class'), (item, index) => {
console.log(`Item: ${item}, index: ${index}`);
});
[].forEach.call(document.querySelectorAll('a'), a => {})
Array.from(document.querySelectorAll('a')).forEach(a => {})
[].forEach.call( document.querySelectorAll('a'), function(el) {
// whatever with the current node
});
var arr = document.querySelectorAll('a');
arr.forEach(function(el) {
// whatever with the current node
});