调试技术

浏览器调试工具

使用浏览器开发者工具调试。

开发者工具

// 打开开发者工具
// Windows: F12 或 Ctrl+Shift+I
// Mac: Cmd+Option+I

// Elements面板:查看和编辑DOM
// Console面板:执行JavaScript
// Sources面板:调试源代码
// Network面板:查看网络请求
// Performance面板:性能分析
// Memory面板:内存分析
// Application面板:存储和应用

Console调试

// 基本输出
console.log("普通日志");
console.info("信息日志");
console.warn("警告日志");
console.error("错误日志");

// 格式化输出
console.log("用户: %s, 年龄: %d", "东巴文", 25);

// 对象输出
const user = { name: "东巴文", age: 25 };
console.log(user);
console.table(user);
console.dir(user);

// 分组输出
console.group("用户信息");
console.log("姓名:", user.name);
console.log("年龄:", user.age);
console.groupEnd();

// 计时
console.time("操作");
for (let i = 0; i < 1000000; i++) {}
console.timeEnd("操作");  // 操作: 2.5ms

// 计数
console.count("点击");
console.count("点击");
console.count("点击");  // 点击: 3

// 断言
console.assert(1 === 2, "断言失败");

// 清空控制台
console.clear();

// 堆栈跟踪
function a() { b(); }
function b() { c(); }
function c() { console.trace(); }
a();

断点调试

使用断点暂停代码执行。

debugger语句

function calculateTotal(items) {
    debugger;  // 代码在此暂停
    
    let total = 0;
    for (const item of items) {
        total += item.price * item.quantity;
        debugger;  // 每次循环暂停
    }
    
    return total;
}

条件断点

// 在开发者工具中设置条件断点
// 右键行号 → Add conditional breakpoint
// 输入条件,如: i > 5

function processArray(arr) {
    for (let i = 0; i < arr.length; i++) {
        // 条件断点: i === 5
        console.log(arr[i]);
    }
}

断点类型

// 1. 代码断点:在Sources面板点击行号
// 2. 条件断点:右键行号添加条件
// 3. DOM断点:Elements面板右键元素
//    - subtree modifications: 子树修改
//    - attribute modifications: 属性修改
//    - node removal: 节点删除
// 4. XHR断点:Sources面板右侧XHR/fetch breakpoints
// 5. 事件监听断点:Sources面板右侧Event Listener Breakpoints

Sources面板调试

使用Sources面板进行调试。

调试控制

// 调试按钮:
// F8 或 Ctrl+\\: 暂停/继续
// F10 或 Ctrl+': 单步跳过
// F11 或 Ctrl+;: 单步进入
// Shift+F11: 单步跳出
// Ctrl+.: 单步执行

// Scope面板:查看变量作用域
// Call Stack面板:查看调用堆栈
// Watch面板:监视表达式

监视表达式

// 在Watch面板添加表达式
// 可以监视变量、属性、计算结果

function processUser(user) {
    const name = user.name;
    const age = user.age;
    const isValid = name && age >= 0;
    
    // 监视:
    // user.name
    // user.age
    // isValid
    // name.length
    
    return isValid;
}

调用堆栈

// Call Stack面板显示函数调用链
function a() {
    b();
}

function b() {
    c();
}

function c() {
    debugger;  // 查看调用堆栈
    // Call Stack:
    // c
    // b
    // a
    // (anonymous)
}

网络调试

调试网络请求。

Network面板

// Network面板功能:
// 1. 查看所有网络请求
// 2. 查看请求/响应头
// 3. 查看响应内容
// 4. 查看请求时间
// 5. 模拟网络速度
// 6. 禁用缓存

// 过滤请求
// XHR: Ajax请求
// JS: JavaScript文件
// CSS: 样式文件
// Img: 图片
// Doc: 文档

请求调试

// 查看请求详情
fetch("/api/user")
    .then(response => {
        // 在Network面板查看:
        // - Request URL
        // - Request Method
        // - Status Code
        // - Request Headers
        // - Response Headers
        // - Response Body
        return response.json();
    });

性能调试

分析和优化性能。

Performance面板

// 记录性能
// 1. 打开Performance面板
// 2. 点击Record
// 3. 执行操作
// 4. 停止记录

// 分析结果:
// - FPS: 帧率
// - CPU: CPU使用率
// - Network: 网络请求
// - Timings: 关键时间点
// - Main: 主线程活动

性能API

// performance API
console.log("页面加载时间:", performance.timing.loadEventEnd - performance.timing.navigationStart);

// 标记时间
performance.mark("start");
doSomething();
performance.mark("end");

// 测量
performance.measure("doSomething", "start", "end");
const measures = performance.getEntriesByName("doSomething");
console.log("耗时:", measures[0].duration);

// 清除标记
performance.clearMarks();
performance.clearMeasures();

长任务检测

// 检测长任务
const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        console.log("长任务:", entry.duration + "ms");
    }
});

observer.observe({ entryTypes: ["longtask"] });

内存调试

分析和修复内存问题。

Memory面板

// Memory面板功能:
// 1. Heap snapshot: 堆快照
// 2. Allocation instrumentation on timeline: 分配时间线
// 3. Allocation sampling: 分配采样

// 内存泄漏检测:
// 1. 创建基准快照
// 2. 执行操作
// 3. 创建新快照
// 4. 比较快照

内存分析

// 常见内存泄漏
// 1. 全局变量
var globalVar = largeObject;  // 泄漏

// 2. 闭包
function createClosure() {
    const largeData = new Array(1000000);
    return function() {
        return largeData.length;  // 持有largeData引用
    };
}

// 3. 事件监听
element.addEventListener("click", handler);
// 忘记移除

// 4. 定时器
setInterval(() => {}, 1000);
// 忘记清除

// 解决方案
// 1. 使用局部变量
// 2. 及时清理引用
// 3. 移除事件监听
// 4. 清除定时器

移动端调试

调试移动设备上的网页。

远程调试

// Android Chrome调试
// 1. 手机开启USB调试
// 2. 连接电脑
// 3. chrome://inspect

// iOS Safari调试
// 1. iPhone设置 → Safari → 高级 → Web检查器
// 2. Mac Safari → 开发 → [设备名]

// 模拟移动设备
// Chrome DevTools → Toggle device toolbar
// 或 Ctrl+Shift+M

响应式调试

// 设备模拟
// 1. 选择预设设备
// 2. 自定义分辨率
// 3. 模拟网络速度
// 4. 模拟触摸事件

// 媒体查询调试
// Elements面板右侧 → Media queries

调试技巧

实用的调试技巧。

快速定位问题

// 1. 使用console.trace追踪调用
function problematicFunction() {
    console.trace("调用追踪");
}

// 2. 使用console.table查看数据
const users = [
    { id: 1, name: "东巴文" },
    { id: 2, name: "db-w.cn" }
];
console.table(users);

// 3. 使用copy复制到剪贴板
copy(JSON.stringify(user));

// 4. 使用$0获取选中的元素
// 在Elements面板选中元素后
console.log($0);

// 5. 使用$_获取上一个结果
1 + 1;
console.log($_);  // 2

调试异步代码

// 使用async/await调试
async function fetchData() {
    debugger;
    const response = await fetch("/api/data");
    debugger;
    const data = await response.json();
    debugger;
    return data;
}

// 使用Promise链调试
fetch("/api/data")
    .then(response => {
        debugger;
        return response.json();
    })
    .then(data => {
        debugger;
        console.log(data);
    });

条件日志

// 条件日志函数
function debugLog(condition, ...args) {
    if (condition) {
        console.log(...args);
    }
}

const DEBUG = true;

debugLog(DEBUG, "调试信息");
debugLog(DEBUG, "用户数据:", user);

// 使用装饰器模式
function withDebug(fn, debug = false) {
    return function(...args) {
        if (debug) {
            console.log(`调用 ${fn.name}`, args);
        }
        const result = fn.apply(this, args);
        if (debug) {
            console.log(`返回`, result);
        }
        return result;
    };
}

下一步

掌握了调试技术后,让我们继续学习:

  1. 性能优化基础 - 学习性能优化
  2. JavaScript优化 - 学习代码优化
  3. 创建型模式 - 学习设计模式

东巴文(db-w.cn) - 让编程学习更简单

🎯 东巴文寄语:调试是开发过程中必不可少的技能,熟练使用浏览器开发者工具、断点调试、性能分析等技巧可以大大提高问题定位效率。在 db-w.cn,我们帮你成为调试专家!