最稳妥的DOM操作是先用getElementById或querySelector获取元素,再检查是否为null;优先用textContent防XSS,批量更新用DocumentFragment减少重排,修改样式用classList而非className。

用 getElementById 或 querySelector 获取元素最稳妥
直接操作 DOM 前必须先拿到目标元素,getElementById 性能好、语义明确,适合有唯一 id 的场景;querySelector 更灵活,支持 CSS 选择器(如 .item、[data-type="alert"]),但要注意它只返回第一个匹配项。
常见错误:用 getElementsByClassName 返回的是 HTMLCollection,不是单个元素,直接调用 .innerHTML 会报 undefined is not an object。
- 优先写
const el = document.getElementById('my-box'),再判断el是否为null - 用
querySelector时,建议加空格容错:document.querySelector('.container .content')比document.querySelector('.container.content')更不易误匹配 - 避免在 DOM 尚未加载完成时查询,脚本放
</body>前,或包裹在DOMContentLoaded事件里
textContent 和 innerHTML 别混用
textContent 只处理纯文本,自动转义 HTML 字符(比如把 <script> 当成文字显示),适合防 XSS;innerHTML 解析并渲染 HTML,功能强但有安全风险。
典型问题:想显示用户输入的“<b>hello</b>”,却用了 textContent,结果页面上真出现了带尖括号的字符串。
立即学习“Java免费学习笔记(深入)”;
- 展示用户可控内容(如评论、表单输入)一律用
textContent - 需要插入结构化 HTML(如动态生成按钮、列表项)才用
innerHTML,且务必先过滤或转义(可用DOMPurify.sanitize()等库) - 修改文本内容时,
textContent比innerText更可靠(后者受 CSS 样式影响,可能返回空字符串)
批量更新用 DocumentFragment 减少重排
循环中反复设置 innerHTML 或 appendChild 会触发多次 DOM 重排,性能差。把多个节点先塞进 DocumentFragment,再一次性挂载到真实 DOM。
示例:动态生成 100 个 <li>,不用 Fragment 时页面可能卡顿;用之后几乎无感。
- 创建方式:
const frag = document.createDocumentFragment() - 往
frag里 append 元素,和操作真实 DOM 一样 - 最后执行
parentElement.appendChild(frag),此时只触发一次重排 - 现代框架(React/Vue)底层也用类似思路,但手写 JS 时容易忽略这点
修改样式优先用 className 或 classList
直接改 style.color = 'red' 是内联样式,优先级高但难维护;通过切换 CSS 类名更符合关注点分离原则,也方便复用动画、响应式等规则。
常见疏漏:用 className = 'active' 会覆盖原有所有 class;而 classList.add('active') 是追加,classList.toggle('active') 自动切换。
- 增删多个类名:
el.classList.add('a', 'b')、el.classList.remove('x', 'y') - 检查是否存在:
el.classList.contains('disabled'),比正则匹配className字符串更安全 - IE10+ 支持
classList,若需兼容 IE9,可用className拼接 + 正则,但务必注意空格边界











