回调函数
杯子是一个段落,#cup,一开始是 blank。这一页没有水壶的定时器。
serve 接收一份订单和一个函数。那个函数就是回调:你交出去,serve 来调用。调用发生在 serve 返回之前,所以下一行已经看见饮料。这一行是 lida tea / poured。
不是水壶
上一页马上记下 cold,hot 要等 400 毫秒。那一行是 cold / hot / 3。定时器会等。serve 不等。如果你在找 setTimeout,这个柜台不是那个。
问题是:你交出去的函数,由谁来调用?
参数名只是一个名字
在 serve 里面,参数叫 done。在调用处,函数没有名字。serve 不在乎名字。它在乎自己收到了一个函数,并且用一个参数调用它:订单加上 tea 这个词。
调用发生在返回之前
done(order + " tea") 先执行,杯子被写上饮料,然后 serve 才结束。调用下面的那条日志已经是饮料。
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。
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 不接收饮料。它只标记倒好了。
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 在拼接这一行之前调用两个函数。
<!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 是上一页。
在柜台
- 把一个函数交给
serve,让它用饮料去调用。日志是 lida tea。 - 用一个从不调用
done的serve。日志停在 blank。 - 交出
done和after。日志是 lida tea / poured。 - 读页面那一行: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
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部