JS实现段落点击编辑时出现Cannot read property 'nodeName' of null报错如何解决
报错原因
- 错误出现在
catchIt函数的节点遍历逻辑中:两个向上查找父节点的while循环未做空值校验,当遍历到document之上的层级时,obj会被赋值为null,此时访问obj.nodeName就会抛出你遇到的空属性读取错误。 - 本质是你将点击事件绑定在全局
document上,所有页面点击都会触发遍历逻辑,部分极端场景下遍历链路超出DOM根节点就会触发空值报错。
修复方案
只需要修改catchIt函数的遍历逻辑,每一步都增加空值判断即可,修改后的完整代码如下:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <p>jobgo</p> <script type="text/javascript"> var editing = false; if (document.getElementById && document.createElement) { var butt = document.createElement('BUTTON'); var buttext = document.createTextNode('Ready!'); butt.appendChild(buttext); butt.onclick = saveEdit; } function catchIt(e) { if (editing) return; if (!document.getElementById || !document.createElement) return; if (!e) var obj = window.event.srcElement; else var obj = e.target; // 第一个循环增加obj非空判断 while (obj && obj.nodeType != 1) { obj = obj.parentNode; } // 提前判断obj为空直接返回 if (!obj || obj.tagName == 'TEXTAREA' || obj.tagName == 'A') return; // 第二个循环增加obj非空判断 while (obj && obj.nodeName != 'P' && obj.nodeName != 'HTML') { obj = obj.parentNode; } // 空值判断兜底 if (!obj || obj.nodeName == 'HTML') return; var x = obj.innerHTML; var y = document.createElement('TEXTAREA'); var z = obj.parentNode; z.insertBefore(y,obj); z.insertBefore(butt,obj); z.removeChild(obj); y.value = x; y.focus(); editing = true; } function saveEdit() { var area = document.getElementsByTagName('TEXTAREA')[0]; var y = document.createElement('P'); var z = area.parentNode; y.innerHTML = area.value; z.insertBefore(y,area); z.removeChild(area); z.removeChild(document.getElementsByTagName('button')[0]); editing = false; } document.onclick = catchIt;</script> </body> </html>
核心修改点
- 所有访问
obj属性的代码前都增加了obj非空校验,避免读取空值属性 - 遍历逻辑增加了兜底判断,只要
obj为空直接终止当前点击事件的处理逻辑
内容的提问来源于stack exchange,提问作者Noob
相关产品推荐
相关产品推荐

