第 36 章 调试
第 36 章 调试
代码写错了怎么办?调试就是帮你找到并修复 bug 的过程。JavaScript 提供了多种调试工具,让 bug 无所遁形。
36.1 console
log / warn / error / info
1
2
3
4
5
6
7
8
9
10
11
| // log:普通日志
console.log('这是一条普通日志');
// warn:警告
console.warn('这是一条警告');
// error:错误
console.error('这是一条错误');
// info:信息
console.info('这是一条信息');
|
%s / %d / %o 格式化 / %c 自定义样式
1
2
3
4
5
6
7
8
9
10
11
12
13
| // %s:字符串
console.log('Hello, %s!', 'World'); // 打印结果: Hello, World!
// %d:数字
console.log('年龄:%d', 18); // 打印结果: 年龄:18
// %o:对象
const obj = { name: '小明', age: 18 };
console.log('对象:%o', obj);
// %c:自定义样式
console.log('%c红色文字', 'color: red; font-size: 20px');
console.log('%c蓝色%c红色', 'color: blue', 'color: red');
|
assert / group / count / time / trace / table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| // assert:断言
console.assert(1 === 1, '这行不会打印');
console.assert(1 === 2, '这行会打印,因为条件不满足');
// group:分组
console.group('用户信息');
console.log('姓名:小明');
console.log('年龄:18');
console.groupEnd();
// count:计数
function test() {
console.count('函数调用次数');
}
test(); // 打印结果: 函数调用次数: 1
test(); // 打印结果: 函数调用次数: 2
// time / timeEnd:计时
console.time('耗时操作');
for (let i = 0; i < 1000; i++) {}
console.timeEnd('耗时操作'); // 打印结果: 耗时操作: 1.23ms
// trace:堆栈跟踪
function a() { b(); }
function b() { c(); }
function c() { console.trace('调用栈'); }
a();
// table:表格显示
const users = [
{ name: '小明', age: 18 },
{ name: '小红', age: 20 }
];
console.table(users);
|
下一节,我们来学习断点调试!
36.2 断点调试
debugger 语句
在代码中加入 debugger 语句,浏览器会在该位置自动暂停执行。
1
2
3
4
5
6
7
8
9
10
| function calculateSum(n) {
let sum = 0;
debugger; // 程序会在这里暂停
for (let i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
console.log(calculateSum(10));
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // 普通断点:在 Sources 面板点击行号
function buggyFunction() {
let result = 0; // 在这行点击设置断点
for (let i = 0; i < 10; i++) {
result += i;
}
return result;
}
// 条件断点:右键点击行号,输入条件
// 当 i === 5 时暂停
function conditionalBreakpoint() {
for (let i = 0; i < 10; i++) {
console.log(i); // 在这里设置条件断点:i === 5
}
}
// XHR 断点:在 Sources 面板的 XHR Breakpoints 中添加 URL 条件
// 当请求的 URL 包含特定字符串时暂停
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
|
VS Code 断点调试:launch.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // launch.json 配置
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动调试",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/app.js"
},
{
"type": "chrome",
"request": "launch",
"name": "Chrome 调试",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}
|
下一节,我们来学习面板工具!
36.3 面板工具
Network:网络请求分析
Network 面板可以查看所有的网络请求,包括请求头、响应头、响应内容、耗时等。
1
2
3
4
| // 在 Network 面板可以看到这个请求的详细信息
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
|
Performance 面板可以记录页面的性能数据,包括帧率、函数调用耗时、布局计算等。
Memory:内存分析(堆快照 / 泄漏检测)
Memory 面板可以进行堆快照分析,检测内存泄漏。
1
2
3
4
5
6
7
8
9
10
11
| // 内存泄漏示例:闭包导致变量无法释放
function createLeak() {
const largeData = new Array(100000).fill('data');
return function() {
console.log(largeData.length);
};
}
const leaked = createLeak();
leaked(); // largeData 永远不会被释放
|
source map:压缩代码调试
1
2
3
4
5
| // 生产环境使用压缩的 JavaScript
// <script src="bundle.min.js.map" />
// source map 可以让压缩代码的报错指向源代码
// 开发时启用 source map,生产时可以使用
|
本章小结
本章我们学习了调试工具:
- console:log、warn、error、info、assert、group、count、time、trace、table。
- 断点调试:debugger 语句、Chrome DevTools、VS Code。
- 面板工具:Network、Performance、Memory、source map。
调试是每个程序员必备的技能。学会使用这些工具,你就能快速定位并修复 bug。
下一章,我们要学习工具函数——让代码更优雅!