JavaScript中var存储DOM元素后修改innerHTML不生效问题
问题根源
你遇到的差异本质是全局作用域命名冲突,问题出在你声明的变量名name上。
浏览器全局环境默认自带原生属性window.name,这个属性有个特殊规则:它只接受字符串类型的值,任何非字符串值赋值给它时,都会被自动强制转换为字符串存储,根本无法保留DOM对象的引用。
两种写法的执行逻辑差异:
- 拆分写法中,你用
var在全局作用域声明name变量时,var声明的全局变量会直接挂载到window对象上,等价于给window.name赋值。此时你选中的DOM元素会被自动转成"[object HTMLLIElement]"这类字符串,根本不是真实的DOM节点对象。后续执行name.innerHTML = "XYZ"时,只是给一个字符串值新增属性赋值,当然不会对页面DOM产生任何修改效果。 - 单行链式调用写法中,不存在给
name变量赋值的操作,链式调用全程返回的都是真实的DOM元素引用,直接修改它的innerHTML自然可以立刻生效。
验证方式
你可以在变量声明后打印类型和值确认问题:
var name = document.firstElementChild.lastElementChild.lastElementChild.lastElementChild; console.log(typeof name); // 输出为string,而非DOM对象对应的object类型 console.log(name); // 输出字符串"[object HTMLLIElement]"
修复方案
任选一种方式即可解决问题:
- 更换变量名,避开
name这个全局特殊属性名,比如:
var lastListItem = document.firstElementChild.lastElementChild.lastElementChild.lastElementChild; lastListItem.innerHTML = "XYZ"; // 正常生效
- 把代码放到私有作用域中执行,用
let/const声明变量,避免变量挂载到window上产生冲突:
// 立即执行函数创建私有作用域 (function() { const name = document.firstElementChild.lastElementChild.lastElementChild.lastElementChild; name.innerHTML = "XYZ"; // 此处name为作用域内私有变量,不会和window.name冲突,正常生效 })()
补充提示:除了
name之外,全局作用域下top、location、navigator等都是window自带的特殊属性,命名变量时尽量避开这类名字,减少莫名其妙的bug。
内容的提问来源于stack exchange,提问作者Sahil Singh
相关产品推荐
相关产品推荐

