regexp.escape 不是标准 javascript api,浏览器和 node.js 均不支持;需手写 escaperegexp 函数转义 12 个正则特殊字符,注意 须最先处理,且转义仅为第一步,还需防范 redos、校验输入来源与长度。

RegExp.escape 不存在于标准 JavaScript 中 —— 这是很多开发者踩坑的起点。你没法直接调用它,浏览器和 Node.js 原生都不支持。
为什么 RegExp.escape 会报错:ReferenceError
试图写 RegExp.escape('a.b+c?') 会抛出 TypeError: RegExp.escape is not a function 或 ReferenceError。这不是兼容性问题,而是该方法从未被纳入 ECMAScript 标准(截至 ES2024)。TC39 曾多次讨论,但始终未达成共识,也未进入草案阶段。
- Chrome、Firefox、Safari、Node.js v20+ 全都不提供
RegExp.escape - 某些打包工具或旧版 polyfill(如
core-jsv2)曾注入过,但已废弃且行为不一致 - MDN 文档里搜不到这个 API,TypeScript 类型定义里也没有
手写安全转义函数的最小可靠实现
真正起作用的是对正则特殊字符做反斜杠转义。只需覆盖 12 个字符:[ ] ^ $ . | ? * + ( )。注意: 必须最先处理,否则会干扰后续转义。
function escapeRegExp(string) {
return string.replace(/[\^$.*+?()[]{}|]/g, '\$&');
}
-
$&是replace的内置引用,表示匹配到的原字符串,比手写'\' + match更安全(避免重复转义) - 不要用
.replace(/W/g, '\$&')—— 它会误伤 Unicode 字母、下划线、数字等合法字面量 - 如果输入可能含换行符且你要在
/s模式外使用,无需额外处理;^和$的含义取决于 flag,转义只针对字面量意义
实际使用场景中容易漏掉的关键点
转义只是第一步。用户输入进正则后,是否仍可控、是否引入回溯风险,得看你怎么拼接。
- 别写
new RegExp(escapeRegExp(userInput) + '.*')—— 如果userInput是'a*',转义后变成'a\*',但拼上.*后整体是a\*.*,语义正确;可一旦写成escapeRegExp(userInput + '.*'),就完全错了 - 若用于
String.prototype.matchAll或replace,确保 flag 与预期一致,比如g和i要显式传入,别依赖字符串隐式构造 - 服务端用
new RegExp()拼接用户输入时,必须限制输入长度(如 ≤ 100 字符),防止 ReDoS;前端相对宽松,但也不建议放任几 KB 的输入进正则
最常被忽略的不是怎么转义,而是忘了检查输入来源 —— 比如从 URL 参数、localStorage、甚至 DOM textContent 读取的字符串,都可能带不可见控制字符或代理对,它们虽不触发正则注入,但可能破坏匹配逻辑。真要防住,得结合 trim、normalize 和长度校验。










