javascript中html转义仅适用于纯文本内容插入,需先处理&避免重复编码,推荐用映射对象方式;但不能替代textcontent、dom api等安全方案,且对属性值、脚本等上下文无效。

JavaScript 中将 HTML 字符串转义(即把 、<code>>、&、"、' 等字符替换为对应 HTML 实体),是防止 XSS 的基础手段之一,但要注意:它**只适用于将用户输入插入到 HTML 文本内容中(如 textContent 或 innerHTML 前手动转义)的场景**,不能替代更安全的方案(如使用 DOM API 或模板引擎的自动防护)。
手动转义常见字符
最直接的方式是用正则替换关键字符:
function escapeHtml(str) {
if (typeof str !== 'string') return '';
return str
.replace(/&/g, '&')
.replace(/, '/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
⚠️ 注意顺序:必须先转义 &,否则后续替换可能把已生成的 & 里的 & 再次处理,导致错误(比如 变成 <code><)。
更稳妥的写法(推荐)
用映射对象 + replace 避免顺序问题:
const escapeHtml = (str) => {
if (typeof str !== 'string') return '';
const map = {
'&': '&',
'': '>',
'"': '"',
"'": '''
};
return str.replace(/[&"']/g, char => map[char]);
};
这样逻辑清晰、不易出错,也便于扩展其他字符。
不建议直接拼接 innerHTML
即使做了转义,如果把结果赋给 innerHTML,仍需格外小心:
- 转义后的内容只能用于「纯文本上下文」,比如
<div>${escaped}</div>是安全的; - 但如果拼进属性值(如
<div title="${escaped}">),单引号/双引号转义不够,还需额外处理属性边界; <li>更危险的是拼进 <code><script></script>、<style></style>、事件处理器(onclick="...")等执行上下文——这些地方转义 HTML 实体完全无效。 - 插入纯文本:用
element.textContent = userInput—— 自动转义,无需手动处理; - 动态创建元素:用
document.createElement+appendChild+textContent; - 需要渲染富文本?用专门的库(如 DOMPurify)过滤 HTML,而不是自己转义;
- 服务端渲染或前端框架(React/Vue)通常自带 XSS 防护,确保开启默认转义机制(如 React 的
{value}是安全的,但dangerouslySetInnerHTML不是)。
更安全的替代方案
优先使用浏览器原生能力,避免字符串拼接:
手动 HTML 转义只是防御 XSS 的一层薄纱,真正可靠的做法是:区分数据上下文、避免动态插入 HTML、优先使用安全 API。











