网站

Console API | MDN

Chrome DevTools | Google

引入

代码写出 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 === 50

debugger 语句

在代码中写 debugger,效果等同于设置断点。

function calculate(a, b) {
  debugger;
  return a + b;
}

开发者工具打开时,程序会在 debugger 处暂停。工具没打开则忽略。

调试控制按钮

暂停后可以用这些按钮控制执行流程:

按钮快捷键说明
ResumeF8继续执行到下一个断点
Step OverF10执行当前行,不进入函数内部
Step IntoF11进入当前函数内部
Step OutShift + F11从当前函数内部跳出来

调用栈和变量

暂停时右侧面板显示:

Scope(作用域):当前能访问到的所有变量及其值。

Call Stack(调用栈):函数调用的层级关系,可以看到是从哪个函数一路调用到这里的。

点击调用栈中的某个函数,可以查看那一层的变量值。

错误信息解读

常见的错误类型:

ReferenceError:使用了未声明的变量。

console.log(x);

TypeError:值的类型不对,比如对 nullundefined 调用方法。

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 异步编程 理解异步代码的执行顺序。