在这一点上,我有一个问题,确切地说是回调是什么,它与高阶函数有何不同以及它与该概念有何关系回调队列?
来自MDN:Callback function
回调函数是作为参数传递给另一个函数的函数,然后在外部函数内部调用该回调函数以完成某种例程或操作。
看起来高阶函数的定义存在重叠。一个传递给(然后被调用)另一个函数的函数。
这是回调的MDN示例:
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}
processUserInput(greeting);
毫无疑问,到目前为止。
然后我遇到了事件循环和回调队列的想法。
console.log("me first");
setTimeout(function asyncLog() {
console.log("i am the last")
}, 2000);
console.log("me second")
产生seTimeout
函数,实际上是一个JavaScript包装器,它与Web浏览器API(计时器)相互连接。 setTimeout将一个函数(asyncLog)和一个计时器(2000ms)传递给Timer API。
当计时器功能(在网络浏览器中)完成其工作后,将在asyncLog
中发送函数callback queue
并准备在JS调用堆栈中立即在调用堆栈中调用(1)为空,(2)在全局执行上下文中处理了所有内容。
因此,在处理了最后一行console.log("me second")
之后,事件循环将回调函数asyncLog
从回调队列传递到调用堆栈,并执行它。
最终订单是:
me first
me second
i am the last
在第一个示例中,即使我们将greeting
称为“回调”函数,但我的理解表明,回调队列的整个机制都被完全跳过了:我们没有做任何异步的事情,不要与Web浏览器API交互(一切都包含在JS中)。
如果是这样,当它们与回调队列和异步世界无关时,为什么将传递给其他函数的函数称为回调(而不是简单的高阶函数)?
答案 0 :(得分:4)
higher-order function是一个将另一个函数作为参数的函数,和/或将函数返回给其调用方。
callback function是一个传递给另一个函数的函数,期望另一个函数会调用它。
因此,回调本身不一定是高级函数,而是将回调作为参数接收的函数。考虑一个非常常见的情况,即DOM事件侦听器:
elem.addEventListener('click', console.log);
在这里,.addEventListener
是一个高阶函数,它采用另一个函数(console.log
)然后调用该函数。尽管console.log
是这里的回调,但在这种情况下它本身并不充当高阶函数。
事件循环是基础运行时向您公开的一种机制。在这里,我们将想象我们必须使用数组作为队列来手动执行此操作:
const queue = [];
const setTimeout = (f, ...args) => {
queue.push([f, args]);
};
const runQueuedCallbacks = () => {
let queued;
while (queued = queue.shift()) {
let [f, args] = queue;
f(...args);
}
};
setTimeout(console.log, 'first'); // queues a call to log
setTimeout(console.log, 'second'); // queues a call to log
console.log('zero-th'); // directly calls log, prints first
// at this point there's no more code to execute, so runQueuedCallbacks runs
// and sequentially steps through the enqueued callbacks.
在现实生活中,由于诸如微任务解析(这在排队的回调将另一个回调排队时会发生什么?)之类的事情,所以这有点复杂,但这希望应该能为您提供一个不错的画面。
答案 1 :(得分:-1)
高阶函数是将另一个函数作为参数和/或将函数返回给其调用者的函数。在此,作为参数传递的函数称为回调函数。 但是,回调函数也可以是高阶函数,也可以不是。让我们看看示例。
function printString(callbackHof, callback_only, str) {
str +=' concated first';
callbackHof( callback_only,str);
}
function concatFirst(callback_only, str)
{
callback_only(str);
}
function concatAgain(str)
{
str += ' contated again';
console.log(str);
}
printString(concatFirst, concatAgain, 'anything');
为澄清起见,输出为=“先合并再合并的任何内容”。
这里printString()是一个高阶函数,它使用两个函数和一个字符串作为参数。 printString()的函数参数为concatFirst()和concatAgain(),这些concatFirst()和concatAgain()函数根据定义是回调函数。
在这里,concatFirst()既是回调函数又是高阶函数,因为它作为printString()的参数传递,然后还使用concatAgain()回调函数作为其自己的输入。
而且,concatAgain()只是一个回调函数,因为仅使用字符串参数调用而没有其他函数参数。
最后,回调队列是浏览器或JavaScript编译器遵循的机制,可以借助事件循环完美地执行异步和回调操作。