判断变量是否为正则表达式且安全需分两步:一用 object.prototype.tostring.call() 确认 regexp 类型,避免 instanceof 失效;二用 try/catch 调用 new regexp() 验证语法合法,并筛查 (a+)+ 等高危模式防 redos。

判断一个变量是否为正则表达式,还要进一步确认它是否安全,需要分两步:先识别类型,再评估风险。单纯是 RegExp 对象,不代表它能安全使用——比如可能引发 ReDoS(正则表达式拒绝服务)或语法错误导致崩溃。
一、确认变量是 RegExp 类型
JavaScript 中最可靠的方式是用 Object.prototype.toString.call(),它不受原型链污染影响,比 instanceof 更健壮:
-
Object.prototype.toString.call(/abc/g) === '[object RegExp]'→ true -
Object.prototype.toString.call(new RegExp('abc')) === '[object RegExp]'→ true -
Object.prototype.toString.call('/abc/') === '[object String]'→ false(字符串不是正则)
注意:instanceof RegExp 在跨 iframe 或模块环境时可能失效;typeof 对所有对象都返回 "object",无法区分。
二、验证正则表达式是否语法合法
即使变量是 RegExp 实例,其内部 pattern 仍可能被动态构造(如通过 new RegExp(str)),而 str 若含非法语法,会在后续调用 test() 或 exec() 时抛错。因此需提前验证:
- 对字面量正则(如
/\d+/),编译阶段已校验,通常无需额外检查 - 对字符串构造的正则,应尝试用
new RegExp(pattern, flags)并捕获异常 - 示例函数:
try {
new RegExp(pattern, flags);
return true;
} catch {
return false;
}
}
三、初步筛查高危正则模式
安全检查不等于完全规避 ReDoS,但可拦截典型危险结构:
- 避免嵌套量词组合,如
(a+)+、(x+x+)+、(.*a){2,} - 警惕贪婪匹配 + 回溯失控,例如
^(a+)+b$在输入大量a时可能指数级耗时 - 推荐用懒惰量词替代贪婪量词:把
.*换成.*?,把.+换成.+? - 限制重复次数上限,如将
a+改为a{1,100},尤其在用户可控输入场景下
四、实际使用中的建议
生产环境中不应仅依赖单次判断,而应建立防护层:
- 对用户提交的正则字符串,必须先过
isValidRegex(),再做模式审查(如用正则 AST 工具或简单关键词扫描) - 敏感操作(如日志解析、配置注入)中使用的正则,建议预编译并缓存,避免运行时重复构造
- 配合超时机制:用
Promise.race([regexTest(), timeout(50)])防止长时间阻塞 - Java 等后端语言可用
Pattern.compile()捕获PatternSyntaxException,同理处理合法性











