在 JavaScript 中,操作 DOM 是实现动态页面的关键。document.write、innerHTML 和 innerText 是三种常用的方法,但它们的用途、性能和安全机制截然不同。本文将深入解析三者的区别,助你避免常见陷阱,写出更高效的代码。
1. document.write:简单但危险的“原始方法”
作用与语法
功能:直接向 HTML 文档流中插入内容。
语法:document.write(content)
示例:
html
复制
下载
运行
<script>
document.write("<h1>Hello World</h1>");
</script>
核心特点
加载时机敏感:
仅在页面初始加载阶段有效。若在 DOM 加载完成后调用(如点击事件中),会覆盖整个页面!
阻塞渲染:
同步写入内容,会阻塞页面解析,影响性能。
适用场景:
旧式脚本或快速原型开发(不推荐生产环境使用)。
2. innerHTML:强大的“内容构造器”
作用与语法
功能:读取或设置元素的 HTML 结构(包括标签和文本)。
语法:element.innerHTML = "<div>New Content</div>";
示例:
javascript
复制
下载
document.getElementById("container").innerHTML = "<p>动态内容</p>";
核心特点
解析 HTML 标签:
插入的字符串会被解析为 DOM 节点(例如 <br> 会变成换行)。
高风险操作:
直接注入未过滤的字符串会导致 XSS 攻击(如 <img src=x onerror=stealCookies()>)。
性能损耗:
频繁修改会触发重排(Reflow)和重绘(Repaint),大范围更新时建议用 DocumentFragment。
适用场景:
动态插入带格式的内容(如富文本渲染)。
3. innerText:安全的“纯文本处理器”
作用与语法
功能:操作元素的纯文本内容(忽略 HTML 标签)。
语法:element.innerText = "Plain Text";
示例:
javascript
复制
下载
document.querySelector("div").innerText = "<script>不会被解析</script>";
核心特点
自动转义 HTML:
输入内容会被视为纯文本(例如 < 转义为 <),天然防 XSS。
关注视觉呈现:
返回的文本会考虑 CSS 样式(如 display: none 的元素内容不会被包含)。
性能优化:
修改时仅触发文本节点的更新,比重排整个 DOM 更高效。
适用场景:
用户输入展示(如评论、消息框)、无需格式的文本更新。
三者的关键对比
特性 document.write innerHTML innerText
操作目标 整个文档流 指定元素的 HTML 内容 指定元素的纯文本内容
解析 HTML ✅ ✅(作为标签解析) ❌(转义为纯文本)
XSS 风险 ⚠️ 高危(动态注入) ⚠️ 高危(未过滤时) ✅ 安全(自动转义)
加载时机限制 ❗️ 仅页面加载中有效 无限制 无限制
性能影响 ⚠️ 阻塞渲染 ⚠️ 可能触发重排 ✅ 较轻量
适用场景 传统脚本 动态插入带标签的内容 安全展示用户输入
最佳实践与注意事项
弃用 document.write:
现代前端开发中应避免使用(除非特殊场景),因其破坏性和阻塞特性。
安全使用 innerHTML:
永远对用户输入进行 XSS 过滤(如使用 DOMPurify 库):
javascript
复制
下载
const cleanHTML = DOMPurify.sanitize(userInput);
element.innerHTML = cleanHTML;
首选 innerText 展示文本:
当内容无需 HTML 标签时,innerText 是更安全、更高效的选择。
性能优化:
批量更新 DOM 时,使用 DocumentFragment 或 textContent(类似 innerText,但不考虑样式)。
总结
document.write:即将退役的“老将”,危险且局限。
innerHTML:功能强大的“双刃剑”,需警惕 XSS。
innerText:安全高效的“文本卫士”,适合用户内容展示。
选择合适的工具,才能在安全与性能的平衡中游刃有余!