您现在的位置是:首页 > 严选问答网站首页严选问答
js callback 回调函数深度讲解
- 编辑:翁璐烟
- 2026-11-08 16:54:10
- 来源:网易
js callback 也就是 JavaScript 回调函数,核心概念就是把一个函数当作参数传递给另一个函数,等到指定时机触发之后,再回头执行这个传进去的函数,它是 JavaScript 异步编程最基础的实现方式,因为 JS 本身是单线程运行,遇到定时器网络请求文件读取这类耗时操作的时候,不能阻塞主线程,就依靠 callback 把后续要执行的代码提前传入,等异步任务完成之后自动调用这个回调,很多初学者容易混淆,以为 callback 是特殊语法关键字,实际上它只是一种编程设计模式,本质依然是普通函数,只是调用时机由外部函数决定,后续出现的 Promise async await 都是在 callback 基础上演进,用来解决回调地狱的痛点。
核心原理讲解
1 函数是一等公民 JS 里面函数可以赋值给变量,可以作为参数传递,也可以作为返回值,这是 callback 能够实现的底层基础
2 执行顺序 主代码优先同步执行,异步任务交给浏览器内核或者运行环境处理,任务完成之后,事件循环机制取出 callback 放入任务队列,等待主线程空闲再执行
3 触发时机 不是传入的时候立刻运行,是等到预设事件完成之后才执行,比如请求成功 请求失败 定时器计时结束 点击事件触发
基础代码示例
function testCallback(data, callback){
console.log("主函数开始执行")
callback(data)
}
testCallback(10, function(res){
console.log("callback执行,结果是", res)
})
分类清单
1 同步回调 传入的回调在当前函数内部立刻执行,不会进入异步队列,比如数组 forEach map 里面传入的函数,属于同步 callback
2 异步回调 回调会延迟执行,交给事件循环调度,比如 setTimeout ajax 请求里面的回调,属于异步 callback,也是面试最常考的类型
回调地狱问题
当多层异步操作需要依赖上一层结果的时候,就会多层 callback 嵌套,代码横向不断缩进,结构变成金字塔形状,就是回调地狱,代码可读性差,错误处理麻烦,维护难度很高,这个就是后续推出 Promise 的主要原因
示例嵌套结构
ajax(url1, function(res1){
ajax(url2, function(res2){
ajax(url3, function(res3){
// 多层嵌套
})
})
})
关键知识点对照表
| 项目 | 同步 callback | 异步 callback |
|---|---|---|
| 执行时机 | 当前调用栈立即执行 | 等待任务完成之后执行 |
| 是否阻塞主线程 | 会按顺序执行 | 不会阻塞主线程 |
| 典型场景 | forEach sort | setTimeout ajax |
| 事件循环 | 不进入任务队列 | 进入宏任务或者微任务队列 |
常见易错点
1 误区 传参的时候写 callback (),这样会立刻执行函数,不是传递函数本身,正确写法是只写函数名或者匿名函数,不带括号
2 误区 所有 callback 都是异步,数组迭代方法里面的回调属于同步回调,这个是高频面试坑
3 错误处理 传统 callback 一般约定第一个参数是错误对象,也就是 error first 风格,如果出错就把 error 传给回调,成功就传数据
综合来看 js callback 是 JS 异步编程的基础,理解函数传参和事件循环,分清同步异步回调,知道回调地狱的缺陷,就掌握这个知识点,后续学习 Promise 的时候也更容易理解它为什么出现。
【常见问题】
问题 1 js callback 是不是就是异步函数
回答 1 js callback 不全是异步函数,callback 只是函数传参的模式,数组 forEach 里面的回调属于同步 callback,只有定时器网络请求里面的回调才是异步 callback
问题 2 js callback 为什么会出现回调地狱
回答 1 js callback 多层异步依赖的时候会不断嵌套回调,缩进越来越深,代码难以阅读维护,也就是回调地狱,后面 Promise 就是用来解决这个问题
问题 3 js callback 传参的时候为什么不能加括号
回答 1 js callback 如果写 callback 括号就会立刻执行这个函数,得到执行结果再传参,不是把函数本身传递进去,所以传递回调的时候不能加括号
【免责申明】
本内容基于 JavaScript 标准语法与前端通用开发知识整理,不同运行环境事件循环细节存在差异,代码仅用于学习演示,不直接等同于生产项目最佳方案。