功能说明
escapeHtml 把与号、小于号、大于号、双引号和单引号替换为实体,escapeHtmlAttribute 在此基础上把换行转换为数字实体,escapeHtmlTemplate 提供带标签模板的便捷写法。它们用于服务端渲染、邮件模板和字符串拼接场景,确保用户输入被当作文本而不是标记解析。输出仍是字符串,不会自动添加引号或包裹元素。
关键代码
替换使用一次性正则与实体映射表,避免多次遍历和链式替换导致的二次转义问题。映射表包含单引号,因为属性常使用单引号包裹;属性函数额外处理 CRLF 与 LF,防止多行值破坏属性结构。标签模板版本对插值逐个转义,静态片段保持原样,适合在代码中书写少量 HTML 片段。
使用注意
手工转义只能处理文本节点和带引号属性,不能替代 HTML 净化。不要把结果再放进未加引号的属性、script、style 或 URL 协议位置,这些上下文需要各自的编码规则。双转义会让 & 显示为字面实体,拼接前应确认值尚未转义。现代框架默认转义插值,只有在明确拼接原始 HTML 时才需要此函数。
验证方式
测试五个特殊字符分别被替换,连续特殊字符不会漏转义。验证属性函数把换行转为 ,并测试 CRLF 与 LF 两种输入。用标签模板拼接用户输入,断言尖括号被转义且静态片段完整。最后测试数字、null、undefined 与对象输入会被 String 转换,并确认没有引入反斜杠或重复转义。
代码示例
const HTML_ENTITIES = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'",
};
export function escapeHtml(value) {
return String(value).replace(/[&<>"']/g, (character) => HTML_ENTITIES[character]);
}
export function escapeHtmlAttribute(value) {
return escapeHtml(value).replace(/\r?\n/g, " ");
}
export function escapeHtmlTemplate(strings, ...values) {
return strings.reduce((output, chunk, index) => {
const value = index < values.length ? escapeHtml(values[index]) : "";
return output + chunk + value;
}, "");
}