1. 变量认知偏差
比如刚刚那个修转变量的例子,新手程序员最好办犯的毛病就是把变量当成是“死物”。你明明知道那个变量在别的地方被改了,但你脑子里还留着旧印象,认定它就是那件被换了颜色的衣服,结局一调用函数,它又变回原样了。
示例:变量污染
// 预期:全局变量保持初始值
// 实际:被匿名函数修改
let count = 0;
function modify() { count = 10; }
modify();
console.log(count); // 输出 10,而非预期的 0
这时候你再想查,发现查不到,不得不质疑是不是自己记错了,要么是不是这把“内存剪刀”剪错了地方。这时候,修转变量的习惯,就变成了一种潜在的 Bug,它会让调试过程变成一场永无休止的鸡同鸭讲。
2. 前后端参数错位
再比如前端和后端不搭界的情况。你在后端写个接口,参数传进去是 100,结局前端拿到的却是 0。这看起来像是一个 Bug,但更深层的缘由可能是,后端默认读取的是下一秒的工夫戳,而前端却期待的是上一秒的。这种工夫线错位,就像两个人背着同一个书包,会儿往前走待会儿就走,脑子里的参考点不一样,最终走到终点,一个认定自己还背着书包,一个认定自己两手空空。
3. 并发与线程冲突
还有一种情况,是“并发 Bug”。比方说,两个线程与此同时访问同一个资源,结局其中一个被锁锁住了,整个系统就停摆。这种 Bug 往往和线程模型相关,和代码写得有多优雅无涉。有时候,代码写得再完美,只要并发场景没处理好,就是个 Bug。
⚠️ 典型场景:竞态条件
当两个线程同时读取、修改并写入同一变量时,最终结果取决于线程调度的顺序,这导致了不可预测的行为。
4. 环境差异
还有那些在测试环境跑通了,却在造环境炸掉的 Bug。测试环境数据都是白天的,造环境数据都是晚上的。白天大家都上班,晚上大家下班,数据量不一样,负载不一样,测试结局自然就不一样。这就像考试,白天考好办,晚上全睡会,分数自然就不一样了。这种环境差异带来的 Bug,是真世界的复杂性在代码层面的投影。
5. 数据源与文档错误
有时候,Bug 还是“数据源 Bug”。比方说,从 Excel 导进来数据,格式乱了,后来发现是导文件本身有隐患,不是代码的难题。这时候,Bug 的源头不在代码,而在数据源。这种“数据致错”,往往比逻辑错更让人痛心。
还有一种情况,是“文档 Bug”。比方说,开发文档里写的是用 Python 写的,结局实际部署了 Java。这时候文档就变成了一个庞大的坑,开发者们对着文档发呆,不知道该用啥语言去写,要么该用啥语言去改。这种“文档和代码不符”的情况,往往比代码本身还难调试。
6. 兼容性陷阱
有时候,Bug 就连是一种“设计上的妥协”。比方说,为了赞成旧设备,写了一个兼容模式。结局目前新设备一来,兼容性模式就卡死了。这时候,解决方案往往是不准开启兼容模式,但这又违背了“向后兼容”的原则。这种两难境地,有时候就是所谓的“兼容性 Bug”。