回调

回调 属于 JavaScript

2 个练习

关于 回调

_回调_函数是作为实参传给其他函数的函数。之后可以调用这个回调函数,以触发后续的操作。回调常用来处理已完成工作的结果,或在事件发生时处理相应的操作。回调函数既可以用于同步编程,也可以用于异步编程。

const sideLength = 5;

// Caller function takes a callback function
function applySideLength(callback) {
  return callback(sideLength);
}

// Callback must expect the possible argument from the calling function
function areaOfSquare(side) {
  return side * side;
}

applySideLength(areaOfSquare); // => 25

你也可以把回调写成函数表达式:

applySideLength(function squarePerimeter(side) {
  return side * 4;
});

这种模式在 JavaScript 中很有用,因为 JavaScript 被设计成单线程的运行时,同一时刻只能执行一个函数调用。在执行期间,运行时无法响应其他事件,也无法继续执行,直到该函数返回为止。

很多 API 调用(I/O 函数、定时器和事件监听器)会使用异步机制,把当前函数调用先放到一边,直到工作完成。完成后,回调函数会被放入消息队列,这样当运行时处于两次函数调用之间时,就会通过调用回调函数来处理这些消息。

使用回调函数还有一个好处:它可以引用自己闭包作用域中的变量,而稍后调用它的那个函数无法访问这些变量。

回调函数的具体例子

事件处理器

事件处理器是 JavaScript 中回调最常见的用途之一。像'onload'或'onclick'这样的浏览器事件,是可以触发函数调用的信号。一个 DOM [文档对象模型对象的addEventListener方法会注册一个回调函数,当它“听到”某个事件已经发生时,就会调用这个回调。

document.addEventListener('onload', function () {
  alert('The webpage has now been loaded');
});

Node.js 惯例

在 Node.js 中,回调函数遵循一套惯例来控制程序的流程。它们遵循这样的模式:回调函数的第一个实参可能收到一个 Error 或 null;第二个及后面的实参接收调用函数要发送的数据。

如果发生错误,第二个及后面的实参可能不存在,所以不能指望它们一定存在。

function operation(a, b, callback) {
  // Work ...

  if (/* an error occurs */) {
    return callback(new Error('An error occurred'))
  }

  // On success:
  callback(null, data)
}

function callback(error, returnedData) {
  if (error) {
    // An error occurred, handle it here.
    return
  }

  // No error occurred, continue with the returned data.
}

operation(1, 2, callback)

在处理异步函数以协助控制流程时,你会经常看到这种模式。

伪装的回调

常见的 Array 函数使用回调函数来定义自己的行为:

  • Array.prototype.forEach:

    • 接收一个回调,并对数组中的每个元素应用这个回调。

      [1, 2, 3].forEach(function (element) {
        doSomething(element);
      });
      // => doSomething() is invoked 3 times, once with each element
      
  • Array.prototype.map

    • 接收一个回调,对数组中的每个元素应用这个回调,并用结果创建一个新数组。

      [1, 2, 3].map(function (element) {
        return element + 1;
      });
      // => [2, 3, 4]
      
  • Array.prototype.reduce

    • 接收一个回调,对数组中的每个元素应用这个回调,并把结果传给下一次调用。

      [1, 2, 3].reduce(function (runningSum, element) {
        return runningSum + element;
      }, 0);
      // => 6
      
通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 回调