网站
引入
代码写出 bug 是常事,光靠看代码很难找出问题在哪。调试就是通过各种工具查看代码运行时的状态,定位问题出在哪里。
浏览器自带了一套完整的调试工具,配合 console 的各种方法,基本能解决大部分问题。
正文
定义
调试是通过查看代码运行状态、输出信息和设置断点来定位和修复程序错误的过程。
console 方法
console.log()
最基本的输出,用来查看变量值或程序是否执行到某一步。
const name = "Tom";
const age = 18;
console.log(name);
console.log("用户信息:", name, age);console.warn()
输出黄色警告信息,比普通 log 更醒目。
if (age < 0) {
console.warn("年龄不合法");
}console.error()
输出红色错误信息,通常会附带调用栈。
function divide(a, b) {
if (b === 0) {
console.error("除数不能为 0");
return;
}
return a / b;
}console.table()
以表格形式展示数组或对象,适合查看结构化数据。
const users = [
{ name: "Tom", age: 18 },
{ name: "Jack", age: 20 },
{ name: "Mary", age: 22 }
];
console.table(users);console.dir()
以可展开的树形结构显示对象的所有属性。
const element = document.querySelector("div");
console.dir(element);console.group() 和 console.groupEnd()
把多条日志分组显示,方便整理。
console.group("用户信息");
console.log("名字:Tom");
console.log("年龄:18");
console.groupEnd();console.time() 和 console.timeEnd()
测量一段代码的执行时间。
console.time("循环耗时");
let sum = 0;
for (let i = 0; i < 1000000; i++) {
sum = sum + i;
}
console.timeEnd("循环耗时");常见 console 方法
| 方法 | 说明 |
|---|---|
console.log() | 普通输出 |
console.warn() | 警告输出(黄色) |
console.error() | 错误输出(红色) |
console.table() | 表格形式展示数据 |
console.dir() | 树形结构显示对象 |
console.group() | 分组日志 |
console.time() | 开始计时 |
console.timeEnd() | 结束计时 |
console.clear() | 清空控制台 |
console.assert() | 断言,为 false 时输出 |
浏览器开发者工具
按 F12 打开开发者工具,常用面板:
Elements(元素):查看和修改页面 DOM 结构、CSS 样式。
Console(控制台):查看 console 输出,执行 JavaScript 代码。
Sources(源代码):查看源码文件、设置断点、单步调试。
Network(网络):查看所有网络请求的状态、响应内容、耗时。
断点调试
在 Sources 面板找到对应的 JavaScript 文件,点击行号即可设置断点。
程序运行到断点时会暂停,可以查看当前所有变量的值。
行断点
点击行号左侧区域,出现蓝色标记,程序执行到这一行会暂停。
条件断点
右键点击行号,选择 Add conditional breakpoint,输入一个条件表达式。
只有条件为 true 时才会暂停,适合排查循环中的问题。
i === 50debugger 语句
在代码中写 debugger,效果等同于设置断点。
function calculate(a, b) {
debugger;
return a + b;
}开发者工具打开时,程序会在 debugger 处暂停。工具没打开则忽略。
调试控制按钮
暂停后可以用这些按钮控制执行流程:
| 按钮 | 快捷键 | 说明 |
|---|---|---|
| Resume | F8 | 继续执行到下一个断点 |
| Step Over | F10 | 执行当前行,不进入函数内部 |
| Step Into | F11 | 进入当前函数内部 |
| Step Out | Shift + F11 | 从当前函数内部跳出来 |
调用栈和变量
暂停时右侧面板显示:
Scope(作用域):当前能访问到的所有变量及其值。
Call Stack(调用栈):函数调用的层级关系,可以看到是从哪个函数一路调用到这里的。
点击调用栈中的某个函数,可以查看那一层的变量值。
错误信息解读
常见的错误类型:
ReferenceError:使用了未声明的变量。
console.log(x);TypeError:值的类型不对,比如对 null 或 undefined 调用方法。
const obj = null;
console.log(obj.name);SyntaxError:语法写错了,比如缺少括号。
if (true {
console.log("hello");
}RangeError:值超出允许范围,比如数组长度为负数。
const arr = new Array(-1);看错误信息时注意两点:错误类型和出错位置(文件名和行号)。
常用调试策略
打印法:在关键位置加 console.log(),查看变量值是否符合预期。
断点法:设置断点,单步执行,观察每一步的变量变化。
二分法:注释掉一半代码,确认问题在哪一半,逐步缩小范围。
最小复现:把问题代码单独拿出来运行,排除其他干扰因素。
对比法:找一个类似的能正常运行的代码,对比差异。
理解
调试可以理解为破案。
console.log() 是最基础的线索收集方式,到处打日志看数据走到哪一步出了问题。
断点调试更像暂停时间,让你慢慢查看案发现场的每一个细节:变量值是多少、函数是从哪里来的、执行顺序对不对。
错误信息就是案发现场留下的证据,看清楚什么错误和在哪里出错,大部分问题就能定位了。
好的调试习惯比写代码更重要,能帮你节省大量找 bug 的时间。
引出
调试定位到问题之后,有些错误需要在代码中主动处理,这就是 JS 错误处理 要做的事情。
如果问题涉及网络请求,还需要配合浏览器的 Network 面板来排查,可以结合 JS 异步编程 理解异步代码的执行顺序。