本文通过实际测试对比了JavaScript中正则表达式字面量与new RegExp的执行效率。结果显示,在大量匹配场景下,经过优化的正则配合new RegExp构造函数能显著提升性能,而字面量形式相对较慢。文章还分析了不同浏览器下的表现差异,并指出compile方法虽已弃用但效果类似。
正则表达式性能测试背景
前几天谈了正则匹配 js 字符串的问题:《js 正则学习小记之匹配字符串》 和 《js 正则学习小记之匹配字符串优化篇》。 里面讲到了优化正则起到提升性能的问题,但是能提升多少呢? 于是我去测试了,发现TMD几乎微乎其微,我用1千字符串进行100万次匹配测试,优不优化根本没区别。

这一结果令人费解,难道之前的正则学习都白费了?
随后想到compile方法,经测试发现,经过优化的正则确实有显著的速度提升。

compile方法与new RegExp的对比
为何会出现这种差异?查阅MDN文档发现,RegExp Methods中明确指出compile方法已被弃用。这似乎与之前的认知相悖。在StackOverflow上找到一篇名为“Javascript: what's the point of RegExp.compile()? ”的文章,指出直接使用new RegExp即可,compile方法几乎无用。基于此,修改代码重新进行测试。

测试结果表明,直接使用new RegExp的效果与compile方法一致。然而,上述结果仅基于Node.js环境,接下来将考察各浏览器下的表现。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<script>
var str1 = '"' + Array(100).join("x") + '123456\\\'78\\\"90"';
var str2 = '"' + Array(100).join("x") + 'ooo\\\\oooo\\\nxxxx\\\"xxxx"';
// 这里写100,小一点,防止等半天,FF那怂货就半天
console.log("字符串1:", str1);
console.log("字符串2:", str2);
var reg1 = /"(?:\\.|[^"])*"/;
var reg2 = /"(?:[^"\\]|\\[\d\D])*"/;
var reg11 = new RegExp('"(?:\\.|[^"])*"');
var reg22 = new RegExp('"(?:[^"\\]|\\[\d\D])*"');
var n = 1e6; //100万次测试
test("reg1", reg1);
test("reg2", reg2);
test("reg11", reg11);
test("reg22", reg22);
function test(name, re) {
console.time(name);
for (var i = 0; i < n; i++) {
str1.match(re);
str2.match(re);
}
console.timeEnd(name);
}
</script>
</body>
</html>
各浏览器环境下的性能表现
chrome
firefox
IE11
IE8 (此处调用了一个插件以模拟控制台,实现IE6-8的调试输出)
从结果来看,Chrome表现最佳(以reg22这种优化后的形式为准),不愧是其名。然而,Firefox的表现甚至不如IE8,显得较为逊色。
结论与建议
优化后的正则比未优化的快,这是显而易见的。但正则字面量与new RegExp相比,性能差距巨大。至于具体原因,目前尚不明确。
以往许多文章认为字面量形式比new对象形式效率更高,但在正则表达式中,情况似乎并非如此。不过,鉴于字面量形式简洁美观且使用便捷,这一观点仍有一定道理,不能直接否定。
在数据量大或重复操作次数多的场景下,使用new RegExp是非常必要的,因为性能提升显著。当然,前提是你的正则表达式必须经过优化;若未优化,两者性能差异不大。因此,优化正则表达式并使用new RegExp可以大幅提升程序性能。
注:IE11是一个特例,其行为往往不按常理出牌。
今天的分享到此结束,希望大家能积极尝试使用new RegExp来优化正则表达式。