回调、高阶函数、回调队列有什么区别

leo*_*fed 7 javascript functional-programming callback

在这一点上,我有一个问题,什么是回调,什么使它与高阶函数不同,它与回调队列的概念有什么关系?

来自 MDN:回调函数

回调函数是作为参数传递给另一个函数的函数,然后在外部函数内部调用该函数以完成某种例程或动作。

看起来与高阶函数的定义有重叠。一个被传递(然后被调用)到另一个函数的函数。

这是回调的 MDN 示例:

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('Please enter your name.');
  callback(name);
}

processUserInput(greeting);
Run Code Online (Sandbox Code Playgroud)

毫无疑问,到目前为止。

然后我遇到了Event LoopCallback queue的想法。

 console.log("me first");

  setTimeout(function asyncLog() {
       console.log("i am the last")
  }, 2000);

  console.log("me second")
Run Code Online (Sandbox Code Playgroud)

原来这个seTimeout函数实际上是一个 JavaScript 包装器,它在底层与 Web 浏览器 API(计时器)交互。setTimeout 将函数 (asyncLog) 和计时器 (2000ms) 传递给计时器 API。

当计时器功能(在网页浏览器)已完成其工作,将发送功能asyncLogcallback queue准备调用堆栈尽快被调用的JS调用堆栈是:(1)空(2)已经处理一切都在全局执行上下文。

所以在处理完最后一行之后,console.log("me second")事件循环将回调函数asyncLog从回调队列传递到调用堆栈,并执行它。

最后的顺序是:

me first
me second
i am the last
Run Code Online (Sandbox Code Playgroud)

在第一个例子中,即使我们指的greeting是“回调”函数,我的理解表明回调队列的整个机制被完全跳过:我们没有做任何异步的事情,我们没有与网络浏览器 API 交互(所有内容都包含在 JS 中)。

如果是这样,当它们与回调队列和异步世界无关时,为什么我们将传递给其他函数的函数称为回调(而不是简单的高阶函数)?

Jar*_*ith 17

高阶函数是一个函数,它的另一功能(一个或多个)作为参数(多个)和/或返回到它的调用者的功能。

一种 回调函数是传递到与其他功能将其称之为期望其他功能的功能。

因此,回调本身不一定是高阶函数,而是接收回调作为参数的函数。考虑一个非常常见的情况,DOM 事件侦听器:

elem.addEventListener('click', console.log);
Run Code Online (Sandbox Code Playgroud)

这里,.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.
Run Code Online (Sandbox Code Playgroud)

在现实生活中,由于诸如微任务解析之类的事情(还有排队回调排队另一个回调时会发生什么),它比这更复杂一点,但这应该会给你一个不错的画面。