JavaScript DOM读取值与UI显示不同步问题咨询
问题根因
- 你拿到的
this.attributes是DOM提供的实时NamedNodeMap引用集合,不是静态快照。只要DOM元素的属性发生修改,这个集合里的内容会自动同步最新值,哪怕你是在修改操作前就完成了遍历。 - 浏览器控制台对引用类型的打印存在懒求值特性:你在控制台点击展开打印的
attr对象时,浏览器才会读取该对象的当前值,此时你后面的if分支修改属性的代码已经执行完成,自然看到的是修改后的text-decoration: line-through;。你添加的alert()只会阻塞代码执行,不会改变引用指向,关闭alert后代码会继续执行修改属性,最终控制台展示的还是更新后的值。
解决方案
要拿到点击触发瞬间的属性静态值,只需要打印基础类型的属性值,或者提前把属性内容做静态快照即可,修改后的代码参考:
var theLi = document.getElementById("here"); theLi.addEventListener("click", crossOff); theLi.setAttribute("style", "color:red;"); theLi.setAttribute("crossed", "off"); function crossOff(element) { var isOn = this.getAttribute("crossed") == "on"; // 方式1:直接打印属性的基础类型值,输出的就是执行到此处的快照值 console.log('当前style值:', this.getAttribute('style')); console.log('当前crossed值:', this.getAttribute('crossed')); // 如果你要遍历所有属性,可以取静态值打印 var attrs = this.attributes; for (const attr of attrs) { // 打印name和value两个基础类型值,不会后续变更 console.log(attr.name, attr.value); } alert("huh??"); if (isOn) { this.setAttribute("style", "text-decoration: none;"); this.setAttribute("crossed", "off"); } else { this.setAttribute("style", "text-decoration: line-through;"); this.setAttribute("crossed", "on"); } }
如果你确实需要打印完整的属性对象快照,可以把实时对象转成普通静态对象再打印:
for (const attr of attrs) { console.log(Object.assign({}, attr)); }
内容的提问来源于stack exchange,提问作者didntgoboom
相关产品推荐
相关产品推荐

