js实战中如何排除代码中的bug错误

📅 2026/7/19 18:24:40 👁️ 阅读次数 📝 编程学习
js实战中如何排除代码中的bug错误

1 术语与 JS 错误完整分类

1.1 三大基础错误类型

1.1.1 语法错误 SyntaxError

代码书写不符合 ES 语法标准,解析阶段直接阻塞执行,代码完全不运行。 常见诱因:少括号、少分号、引号不匹配、关键字误用、解构语法书写错误。

1.1.2 引用 / 类型运行时错误 ReferenceError / TypeError

语法合法,但执行时变量、对象、方法不存在或调用方式非法,执行中断。 高频场景:访问未定义变量、null/undefined调用属性、基本类型调用数组方法、函数传参类型不匹配。

1.1.3 逻辑 Bug(无报错,但结果不符合预期)

无控制台报错、无程序崩溃,仅业务计算、渲染、判断逻辑出错,是项目中最难排查的一类 Bug。 例如:判断条件写反、循环边界错误、异步顺序错乱、深浅拷贝修改原数据。

1.2 其他细分错误

  • RangeError:数值超出合法范围(数组长度负数、递归死循环)
  • URIError:URL 编解码参数非法
  • EvalError:eval 执行异常(极少出现)
  • 异步隐性错误:Promise 未捕获异常、定时器变量作用域污染
  • 环境类错误:跨域 CORS、接口返回数据格式异常、兼容性报错

2 原生调试工具完整使用(DevTools 核心能力)

2.1 浏览器 DevTools Sources 面板(核心排错工具)

2.1.1 断点调试 Breakpoint

  1. 普通行断点:点击代码行号,代码执行到该行自动暂停,查看当前所有变量、作用域。
  2. 条件断点:右键行号 → Add conditional breakpoint,仅表达式为 true 时暂停,适合循环内精准定位异常数据。

javascript

运行

// 示例:仅当 id=0 时断点暂停 const list = [{id:0},{id:1},{id:2}] list.forEach(item => { // 条件断点填写 item.id === 0 console.log(item) })
  1. DOM 断点:Elements 面板右键元素,监听元素属性修改、子节点变更,定位渲染异常。
  2. XHR/Fetch 断点:Network 面板勾选 XHR/fetch Breakpoints,拦截所有接口请求,查看入参、返回值。

2.1.2 调试控制按钮

  • Resume:放行至下一个断点
  • Step over:逐行执行,跳过函数内部
  • Step into:进入当前调用函数内部
  • Step out:跳出当前函数
  • Watch 监视面板:自定义表达式实时观测变量变化,无需反复 console.log

2.1.3 控制台 Console 调试 API(替代简易打印)

javascript

运行

// 普通打印 console.log("普通日志", data) // 分组打印,层级清晰 console.group("用户列表数据") console.table(userList) // 表格格式化数组/对象 console.groupEnd() // 区分错误、警告 console.warn("参数缺失警告") console.error("接口请求失败") // 打印调用栈,查看函数执行链路 console.trace("当前调用栈") // 性能打点 console.time("循环耗时") for(let i=0;i<1000;i++){} console.timeEnd("循环耗时")

3 各类错误识别、定位、修复实战示例

3.1 SyntaxError 语法错误

错误示例

javascript

运行

// 引号未闭合 const str = "测试文本 // 对象少逗号 const obj = { name:"小明" age:20 }

排查特征

控制台直接标红,提示行号,页面空白 / 脚本完全失效。

修复方案

  1. 根据控制台提示行号检查引号、括号、大括号配对;
  2. VSCode 开启 ESLint,编码阶段实时标红语法问题。

3.2 ReferenceError 引用错误

错误示例

javascript

运行

function getUser() { const name = "张三" } console.log(name) // name 仅函数内作用域,外部无法访问

排查特征

xxx is not defined;变量作用域混淆、变量未声明。

修复方案

  1. 区分var/let/const块级作用域;
  2. 全局变量挂载 window,局部变量提升规则排查。

3.3 TypeError 类型错误(项目最高频 Bug)

场景 1:undefined/null 读取属性

javascript

运行

const res = null console.log(res.name) // Cannot read properties of null (reading 'name')

修复:可选链操作符?.做空值防护

javascript

运行

console.log(res?.name)

场景 2:基础类型调用数组方法

javascript

运行

const data = 123 data.map(item => item) // map is not a function

修复:先判断数据类型Array.isArray(data)再执行数组方法。

3.4 逻辑无报错 Bug 排查流程

  1. 使用console.table打印完整数据源,确认接口返回数据是否符合预期;
  2. 条件断点锁定异常数据条目;
  3. Watch 面板监听判断表达式,确认布尔值是否与预期相反;
  4. 拆解复杂判断,拆分多段if分步打印中间值。

逻辑错误示例

javascript

运行

// 需求:过滤年龄大于18的用户,条件写反 const users = [{age:16},{age:20}] const adult = users.filter(item => item.age < 18)

排查:Watch 输入item.age < 18观察布尔值,快速发现条件逻辑颠倒。

3.5 RangeError 范围错误

javascript

运行

new Array(-1) // Invalid array length // 递归死循环 function loop(){ loop() } loop()

修复:校验数组长度为非负数、递归增加终止条件。


4 编码层主动防御:提前规避 Bug(工程规范)

4.1 空值安全防护

统一使用 ES6 可选链、空值合并,杜绝空对象报错

javascript

运行

// 推荐 const city = user?.address?.city ?? "未知" // 不推荐 const city = user.address.city

4.2 强类型校验

接口返回数据先校验类型,再执行业务逻辑

javascript

运行

function renderList(list) { if(!Array.isArray(list)) { console.error("列表数据必须为数组", list) return [] } return list.map(item => item.name) }

4.3统一异常捕获规范

同步代码 try/catch

javascript

运行

function parseJson(str) { try { return JSON.parse(str) } catch(err) { console.error("JSON解析失败", err) return null } }

Promise 异步捕获

javascript

运行

// 方案1:catch 链 fetch("/api/list") .then(res => res.json()) .catch(err => console.error("接口异常", err)) // 方案2:async/await try catch async function getList() { try { const res = await fetch("/api/list") return res.json() } catch(err) { // 统一异常处理 } }

5 高频复杂场景专项排错指南

5.1 异步 Bug(定时器、Promise、async 时序错乱)

问题代码

javascript

运行

for(var i=0;i<3;i++){ setTimeout(()=>{ console.log(i) // 全部输出3 },100) }

排查手段

断点进入定时器回调,Watch 观测 i 值;

修复:使用 let 块级作用域保存循环变量。

5.2 深浅拷贝修改原数据 Bug

现象:修改新对象,原始数组 / 对象同步变化; 排查:打印两个对象引用地址对比; 修复:简单结构用扩展运算符、复杂结构结构化深拷贝。

5.3 闭包变量污染

特征:多次调用函数,数据互相干扰; 排查:console.trace 打印闭包执行栈,观测自由变量。

5.4 跨域 CORS 报错

特征:控制台 Network 报红色,提示 Access-Control-Allow-Origin; 区分:前端代理跨域、后端配置跨域、JSONP 三种解决方案。

5.5 渲染界面数据不同步(Vue/React)

特征:控制台数据正常,页面不更新; 排查:断点监听响应式数据变更,检查赋值方式、响应式规则。


6 线上生产环境错误捕获与定位

6.1 全局页面异常捕获

javascript

运行

// 捕获同步全局错误 window.onerror = function(message, source, line, column, err) { // 上报错误日志服务 console.log("全局异常", {message, source, line}) } // 捕获未处理Promise异常 window.addEventListener("unhandledrejection", e => { console.log("异步Promise未捕获错误", e.reason) })

6.2 生产环境源码定位

项目打包后代码压缩混淆,需上传 sourcemap,通过错误行号还原原始源码;

6.3 第三方监控工具

Sentry、Fundebug 自动捕获线上报错、携带用户设备、接口参数、堆栈信息,快速复现线上 Bug。


7 标准化排错流程(通用工作流)

  1. 收集错误信息:复制控制台完整报错堆栈、接口返回数据、复现操作步骤;
  2. 区分错误大类:语法错误 / 运行时异常 / 无报错逻辑 Bug;
  3. 缩小范围:注释一半代码二分法定位出错代码块;
  4. 工具断点精准定位:条件断点、XHR 断点、console.table 打印数据源;
  5. 复现最小 Demo:抽离出错代码单独运行,排除外部环境干扰;
  6. 修复并增加防御代码:空值判断、类型校验、try/catch;
  7. 补充单元测试:针对该 Bug 编写测试用例,防止迭代回归。