先来回忆一下回调函数的概念:当函数A被当作参数传给函数B,则函数A被称为回调函数。

    就好比是 arr.forEach(callback) 中就传入了一个匿名函数,这个匿名函数就是一个回调函数。这个 callback 首先能明确:

    1. 它是开发人员自己定义的
    2. 还能明确它不是被开发者亲自调用的,而是被数组的 forEach 方法自动调用的

    阅读代码分析输出:

    1. const arr = [1, 2, 3];
    2. arr.forEach(item => console.log(item));
    3. console.log('嘿嘿');

    输出结果是 1-2-3-嘿嘿
    从输出结果可以看出 forEach 需要将 callback 执行完毕之后,才会执行 log 方法,也就证明了这个 callback 是一个同步回调函数。同样像 map、filter、sort 等等,参数 callback 都是一个同步回调函数。
    再来分析一段代码:

    setTimeout(() => {
        console.log('时间到!');
    }, 0);
    console.log('嘿嘿');
    

    输出结果应该是 时间到-嘿嘿 还是 嘿嘿-时间到 呢?

    实际输出为 嘿嘿-时间到。输出结果并没有像书写顺序那样,原因就是因为计时器里的 callback 是一个异步回调函数,会放进到异步任务队列在将来执行。

    所以在回调函数的分类中,可以被分为两类:

    1. 同步回调函数
    2. 异步回调函数

    现在你知道怎样判断一个任务是同步任务还是异步任务了吗?最简单的判断方式就是在该任务之后写一个 log 语句,如果该 log 语句在任务之后被输出,则为一个同步任务,反之则是异步任务。所以在发送 ajax 请求时,发送请求是个非常快速的行为,但服务器处理、返回结果是需要时间的,那么此时到底是等待请求响应完成还是先接着执行着别的任务,就突出了异步的特点和同步异步的不同了。