首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >回调、高阶函数和回调队列的区别是什么?

问回调、高阶函数和回调队列的区别是什么?
EN

Stack Overflow用户
提问于 2018-07-29 10:35:24
回答 2查看 11.9K关注 0票数 11

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

来自MDN:回调函数

回调函数是作为参数传递到另一个函数中的函数,然后在外部函数中调用该函数来完成某种例程或操作。

看来与高阶函数的定义有重叠之处。传递(稍后调用)给另一个函数的函数。

这是回调的MDN示例:

代码语言:javascript
复制
function greeting(name) {
  alert('Hello ' + name);
}

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

processUserInput(greeting);

毫无疑问到目前为止。

然后,我面对了事件循环和回调队列的思想。

代码语言:javascript
复制
 console.log("me first");

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

  console.log("me second")

实际上,seTimeout函数是一个JavaScript包装器,它与wrapper (timer)接口。setTimeout传递给计时器API函数(asyncLog)和计时器(2000 to )。

当计时器功能(在web浏览器中)完成其工作后,只要JS调用堆栈是(1)空的,并且(2)已经处理了全局执行上下文中的所有内容,callback queue中的函数就会立即发送到callback queue中,以便在调用堆栈中调用。

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

最后的命令是:

代码语言:javascript
复制
me first
me second
i am the last

在第一个例子中,尽管我们将greeting称为“回调”函数,但我的理解表明,回调队列的整个机制被完全跳过:我们没有做任何异步的事情,也没有与web浏览器API接口(所有东西都是自包含在JS中的)。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-30 15:04:51

高阶函数是一个函数,它以另一个函数作为参数,和/或将函数返回给调用者。

回调函数是一个传递给另一个函数的函数,期望另一个函数调用它。

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

代码语言:javascript
复制
elem.addEventListener('click', console.log);

在这里,.addEventListener是一个高阶函数,它接受另一个函数(console.log),然后调用它.虽然console.log在这里是一个回调函数,但在这种情况下,它本身并不是一个高阶函数。

事件循环是由底层运行时向您公开的机制。在这里,我们将设想必须使用数组作为队列手动执行此操作:

代码语言:javascript
复制
const queue = [];
const setTimeout = (f, ...args) => {
  queue.push([f, args]);
};

const runQueuedCallbacks = () => {
  let queued;
  while (queued = queue.shift()) {
    let [f, args] = queued;
    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.

在现实生活中,由于微任务解析(也就是当排队的回调排队等待另一个回调时发生的情况),这比这要复杂一些,但这应该会给您一个不错的印象。

票数 23
EN

Stack Overflow用户

发布于 2019-05-22 18:53:56

高阶函数是将另一个函数作为参数并/或将函数返回给其调用方的函数。这里,作为参数传递的函数被调用为回调函数。但是,回调函数也可能是高阶函数,也可能不是。让我们看看例子。

代码语言:javascript
复制
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编译器在事件循环的帮助下完美地执行异步和回调操作的机制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51579427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档