写bug已经写了一年半多了,今天居然又遇到了一个以前没有遇到过的bug。
我不经陷入深思,是我写bug的能力退化了,还是我已经到了看bug不是bug的境界了?
我是bug工程师,我为自己带盐。
起因
作为一个称职的bug工程师,我一天不整出两三个bug,就老会觉得自己已经跟不上时代了。
然而,今天,写前端界面的时候。
简述一下项目需求,js动态加载以及切换多个悬浮卡片页面。
这个神奇的bug就来源于,我动态插入dom导致绑定点击事件失效。
正常逻辑是,动态插入dom之后,绑定点击事件,进行相应逻辑处理。
但是,惊奇的事情来了。
请看代码
function demo(){
let div = document.createElement('div');
let p = document.createElement('p');
p.innerHTML = 'this is test!';
div.appendChild(p);
p.onclick = function(){
console.log('p click');
}
div.innerHTML += '<p>i love bug</p>';
document.body.appendChild(div);
}
分析
上面的代码,有可能有些人不一定能发现问题,因为整个代码看起来还是比较正常的。
也有可能有细心的人一眼就能看出问题,只是想小声的说一句,我当时debug的时候绑定事件操作是封装到对象的另一个方法中来做的。
也就是说实际项目出现这个bug你可能面临的不是简单的一个函数几行代码,可能是多个调用链以及成百上千行代码。
当然,这些都不重要。
重要的是,我当时就麻了。
起先怀疑是dom没有插入进去,但是一排查,发现dom好好的。
之后排查打印dom对象里面onclick,发现在方法(我当时的代码)结束时它是存在的,上面的示例代码如果在绑定之后打印也会发现确实是绑定上了。
之后就怀疑是绑定的姿势不对,所以用addeventlistener试试。
当然,诡异是没有报错,是的,没有报错信息。
然后我怀疑是创建元素的问题,所以我选择在创建结束后用document.getElementsClassName方法去拿来绑定,然并卵。
整个最诡异的地方就是,那个元素确实是被渲染出来了,而且class绑定也没错。
然后我开始方了,一度怀疑是局部作用域垃圾回收机制给回收了,然而又怀疑是dom立马渲染而我立马就绑定了(也就是说我认为我绑定事件时dom其实还没被渲染出来 以前就犯过这种错误)。
直到最后,走出思维误区,回溯代码,终于发现被自己遗漏的div.innerHTML +=
。
是的,这就是万恶的罪魁祸首。
当时就是图方便图快,谁知道居然给自己埋了个坑。
延伸思考
其实,绑定事件失效的情况并不算特别少见,我有时候因为粗心,会将元素绑定错误,比如说绑定到子元素、同胞元素、命名类似的元素,然后点半天没有反应。
当然除了这种场景,我还遇到过,绑定事件时dom还没有被渲染错误导致的失效以及对象内this指向改变导致绑定失效等情况。
这个bug的神奇之处在于
- dom正常显示
- 没有任何报错信息
- 检查id、class都没有错误
- 代码逻辑咋一看好像也没啥毛病(我自己写的时候是几百行的代码排查哟)
这个bug的相当有意思,当然也觉得自己蠢得很可爱,所以特此记录。
还不快抢沙发