正在加载...

回调函数

杯子是一个段落,#cup,一开始是 blank。这一页没有水壶的定时器。
serve 接收一份订单和一个函数。那个函数就是回调:你交出去,serve 来调用。调用发生在 serve 返回之前,所以下一行已经看见饮料。这一行是 lida tea / poured。

不是水壶

上一页马上记下 cold,hot 要等 400 毫秒。那一行是 cold / hot / 3。定时器会等。serve 不等。如果你在找 setTimeout,这个柜台不是那个。
问题是:你交出去的函数,由谁来调用?

参数名只是一个名字

在 serve 里面,参数叫 done。在调用处,函数没有名字。serve 不在乎名字。它在乎自己收到了一个函数,并且用一个参数调用它:订单加上 tea 这个词。

调用发生在返回之前

done(order + " tea") 先执行,杯子被写上饮料,然后 serve 才结束。调用下面的那条日志已经是饮料。

交出一个函数

javascript
function serve(order, done) {
done(order + " tea");
}
let cup = document.getElementById("cup");
serve("lida", function (drink) {
cup.textContent = drink;
});
console.log(cup.textContent);

日志是 lida tea。杯子没有停在 blank,也没有谁在等。

忘了调用

这个 serve 把饮料拼好就停了。它不调用 done。你交出去的函数就停在那里。杯子在调用前被设成 blank,并且一直是 blank。

不要调用 done

javascript
function serve(order, done) {
order = order + " tea";
}
let cup = document.getElementById("cup");
cup.textContent = "blank";
serve("lida", function (drink) {
cup.textContent = drink;
});
console.log(cup.textContent);

日志是 blank。不会抛出错误。从未被调用的回调根本不执行。饮料字符串做好了,没有人收下。

第二个函数,排在第一个后面

serve 可以接收两个函数。它先用饮料调用 done。只有那次调用返回之后,才调用 after。after 不接收饮料。它只标记倒好了。

先 done 再 after

javascript
function serve(order, done, after) {
done(order + " tea");
after();
}
let seen = [];
serve(
"lida",
function (drink) {
seen.push(drink);
},
function () {
seen.push("poured");
}
);
console.log(seen.join(" / "));

日志是 lida tea / poured。把 serve 里面两次调用对调,词也会对调。顺序是调用的顺序,不是你写下函数表达式的顺序。

页面拼的是什么

页面用的是第二个 serve,带 done 和 after 的那个。先放入饮料,再放入 poured,然后写下这一行。两者之间没有延迟。

杯子下面的那一行

脚本在 body 末尾。serve 在拼接这一行之前调用两个函数。

页面演示 — 杯子

html
<!DOCTYPE html>
<html>
<head>
<title>serve-cup — page</title>
</head>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
function serve(order, done, after) {
done(order + " tea");
after();
}
let seen = [];
serve(
"lida",
function (drink) {
seen.push(drink);
},
function () {
seen.push("poured");
}
);
document.getElementById("line").textContent = seen.join(" / ");
document.getElementById("cup").textContent = seen[0];
</script>
</body>
</html>

这一行是 lida tea / poured。杯子显示 lida tea。blank 没了。cold / hot / 3 是上一页。

在柜台

  1. 把一个函数交给 serve,让它用饮料去调用。日志是 lida tea。
  2. 用一个从不调用 done 的 serve。日志停在 blank。
  3. 交出 done 和 after。日志是 lida tea / poured。
  4. 读页面那一行:lida tea / poured。

柜台上看错的地方

杯子要么显示饮料,要么停在 blank。它不显示间隔的计数。

  • 以为 done 已经调用了,serve 下面的日志还是 blank
  • 以为 serve 不调用,回调也会执行
  • 为了 lida tea 等 400 毫秒
  • 先调用 after,把 poured 放在饮料前面
  • 把这一行读成 cold / hot / 3

记住这些

  • 回调是你交出去、让别人来调用的函数
  • serve 在返回之前调用 done,所以下一行已经看见 lida tea
  • 如果从不调用 done,杯子停在 blank,也不会有错误
  • after 只在 done 返回之后执行
  • 页面这一行是 lida tea / poured

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
6
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部