Js-回调函数

什么是回调函数?

简单来说: 回调函数就是一个函数,它作为参数传递给另一个函数,在这个函数完成某些操作后再调用(回调)这个传递进来的函数。

例子 1:订餐场景

假设你给餐厅打电话订餐(打电话相当于调用函数),你告诉餐厅:

  1. 当饭做好后,请打电话通知我(告诉他们回调一个函数)。
  2. 等饭做好了,他们会回调你给他们的号码(即函数),然后你就接到通知。
// 模拟订餐的函数
function orderFood(callback) {
  console.log("订单已提交,等待饭做好...");
  setTimeout(() => {
    // 3秒钟后通知你
    callback("饭已做好,快来取吧!");
  }, 3000);
}

// 使用函数时,传递一个回调函数
orderFood((message) => {
  console.log(message); // 打印通知:饭已做好,快来取吧!
});

代码说明:

  1. orderFood 是订餐函数,你告诉餐厅完成后给你通知。
  2. callback 是一个回调函数,你传递给 orderFood
  3. 当餐厅完成了任务(饭做好了),调用 callback 给你发送消息。
例子 2:洗衣服的流程

假设你用洗衣机洗衣服,洗衣服这个过程需要一段时间。等洗好后,洗衣机会发出“滴滴”的声音通知你(回调函数)。

function doLaundry(callback) {
  console.log("开始洗衣服...");
  setTimeout(() => {
    // 模拟 3 秒钟的洗衣过程
    console.log("衣服洗好了!");
    callback(); // 回调通知你
  }, 3000);
}

// 使用时传递回调函数
doLaundry(() => {
  console.log("把衣服晾起来!");
});

运行流程:

  1. 先打印:开始洗衣服...
  2. 3 秒后,打印:衣服洗好了!
  3. 然后调用回调函数,打印:把衣服晾起来!

回调函数的好处

  1. 异步操作:当某些操作需要耗时时(比如网络请求、读写文件等),回调函数可以让程序继续运行,不用等待操作完成。
  2. 灵活性:你可以传入不同的回调函数,来定义操作完成后的不同行为。
例子 3:多种回调

假设你在洗衣服时,不同情况下想做不同的事情。

function doLaundry(callback) {
  console.log("开始洗衣服...");
  setTimeout(() => {
    console.log("衣服洗好了!");
    callback(); // 回调通知你
  }, 3000);
}

// 情况 1:晾衣服
doLaundry(() => {
  console.log("晾衣服!");
});

// 情况 2:直接穿上(假设是烘干机洗的)
doLaundry(() => {
  console.log("直接穿衣服!");
});

结果:

  • 第一个调用会输出:
    开始洗衣服... -> 衣服洗好了! -> 晾衣服!
  • 第二个调用会输出:
    开始洗衣服... -> 衣服洗好了! -> 直接穿衣服!

回调函数与同步代码对比

普通同步代码
function sayHello() {
  console.log("你好!");
}

sayHello();
console.log("程序结束");

输出:

你好!
程序结束

异步回调代码

function sayHelloAsync(callback) {
  setTimeout(() => {
    console.log("你好!");
    callback();
  }, 1000);
}

sayHelloAsync(() => {
  console.log("程序结束");
});

输出:
 

你好!(延迟 1 秒打印)
程序结束

常见的回调函数场景

  1. 事件监听  

    const button = document.getElementById("myButton");
    button.addEventListener("click", () => {
      console.log("按钮被点击了!");
    });
    
  2. 定时器

    setTimeout(() => {
      console.log("延迟 2 秒后执行");
    }, 2000);
    
  3. 数组操作(如 mapforEach

const numbers = [1, 2, 3];
numbers.forEach((num) => console.log(num * 2)); // 输出 2, 4, 6
  1. 数组 numbers

    • 定义了一个数组 numbers,它包含 3 个数字:1, 2, 3
  2. forEach 方法

    • forEach 是数组的一个方法,用来遍历数组中的每一项,并对每一项执行一个回调函数。
  3. 回调函数 (num) => console.log(num * 2)

    • 这是一个箭头函数。
    • numforEach 方法自动传入的参数,代表当前遍历到的数组项。
    • 每次遍历时,console.log(num * 2) 会将当前的 num 乘以 2,然后输出到控制台。

运行流程

forEach 会对数组中的每个元素执行回调函数,具体的执行流程如下:

第一次遍历
  • 当前元素是 1,回调函数 console.log(num * 2) 中的 num 就是 1
  • 输出:1 * 2 = 2
第二次遍历
  • 当前元素是 2,回调函数中的 num2
  • 输出:2 * 2 = 4
第三次遍历
  • 当前元素是 3,回调函数中的 num3
  • 输出:3 * 2 = 6

最终结果:

2
4
6

简化理解

你可以把 forEach 理解成一个自动帮你遍历数组的循环,每遍历一个元素,就执行一次你传给它的函数。

手动实现 forEach 的逻辑(模拟)

我们用普通的 for 循环来实现:

const numbers = [1, 2, 3];
for (let i = 0; i < numbers.length; i++) {
  const num = numbers[i];
  console.log(num * 2);
}

运行结果和 forEach 是一样的。

换个更简单的例子:理解回调和遍历

例子 1:输出所有数组元素
const numbers = [1, 2, 3];
numbers.forEach((num) => console.log(num));

运行结果:

1
2
3

这里的回调函数 (num) => console.log(num) 只是简单地把数组中的每个元素打印出来。


例子 2:将每个元素加 5 后打印
const numbers = [1, 2, 3];
numbers.forEach((num) => console.log(num + 5));

运行结果:

6
7
8

每次遍历时,num 会被替换成当前的数组元素,然后加上 5。


map 的区别

如果你想对数组中的每一项进行操作并返回一个新数组,应该使用 map

例子:用 map 返回一个新数组
const numbers = [1, 2, 3];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6]

这里的 map 会将每个元素乘以 2,并返回一个包含结果的新数组,而 forEach 不会返回新数组,只是执行操作。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值