使用 regex.test 和 string.match 判断一个字符串是否匹配一个正则表达式

378

很多时候,我使用字符串的match函数来判断一个字符串是否匹配一个正则表达式。

if(str.match(/{regex}/))

这两种写法有什么区别:

if (/{regex}/.test(str))

看起来它们给出的结果相同?


4
这是你能找到的最好的测试 http://jsperf.com/regexp-test-vs-match-m5。 - ajax333221
@ajax333221。感谢您提供的jsperf,但我不确定它是否是一个好的测试。正则表达式匹配使用了一个匹配组,在查找布尔值时是不必要的。 - gdoron
“一个字符串是否匹配给定的模式?”与“我的模式是否匹配给定的字符串?”相比,“str.match(/ {regex} /)”似乎更容易理解,而不是“/ {regex} / .test(str)”。也许下一代JavaScript应该包括一个“str.like(/ {regex} /)”,它的行为类似于测试,但读起来像匹配。 - PotatoFarmer
2个回答

567

基本用法

首先,让我们看一下每个函数的作用:

regexObject.test( String )

执行正则表达式和指定字符串之间的匹配搜索。返回truefalse

string.match( RegExp )

在将字符串与正则表达式匹配时,用于检索匹配项。返回带有匹配项的数组或null(如果没有匹配项)。

由于null会被视为false

if ( string.match(regex) ) {
  // There was a match.
} else {
  // No match.
} 

性能

在性能方面是否有任何区别?

有的。我在MDN网站上找到了这篇简短的说明:

如果你需要知道字符串是否与正则表达式regexp匹配,请使用regexp.test(string)。

这种差异重要吗?

答案再次是有的!我编写了这个jsPerf测试,显示差异约为30%到60%,具体取决于浏览器:

test vs match | Performance Test

结论

如果你想要更快的布尔检查,请使用.test。如果你使用全局标志g,请使用.match来检索所有匹配项。


8
不太惊讶,因为字符串函数需要翻转内容并检查是否匹配,如果匹配则创建数组。看来我还是会继续使用.test()。 :) - user1106925
37
我的看法是:过分强调性能。两种选项都可以在电脑屏幕闪烁的瞬间完成大约15,000次操作,所以除非你需要在客户端进行批量正则表达式操作,否则速度并不重要。当然,如果你需要布尔结果,那么逻辑上“test”函数是正确的选择。顺便说一句,谢谢提问和回答。 - David Gilbertson
2
有趣的是,使用上面的jsPerf测试(Chrome 41,OSX),对我来说test比match慢了41%。 - Benjie
1
@AlexShilman indexOf 比 test 更快(但不是很多),根据这个链接:https://dev59.com/xEXRa4cB1Zd3GeqPr3Iu(你会期望它更快)。 - podperson
10
有一件事可能会让你措手不及(我们的团队最近遇到了这个问题):如果你在正则表达式中使用 'g' 标志并创建一个新实例(例如通过 new RegExp(<regex_str>,'g')),并且你重复使用该实例,在多次运行“test”时,结果会有状态,即会返回不同的结果。有关详细信息,请参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag。 - davertron
显示剩余7条评论

189

不要忘记在正则表达式中考虑全局标志:

var reg = /abc/g;
!!'abcdefghi'.match(reg); // => true
!!'abcdefghi'.match(reg); // => true
reg.test('abcdefghi');    // => true
reg.test('abcdefghi');    // => false <=

这是因为当找到新的匹配项时,正则表达式会跟踪 lastIndex。


36
我刚才看到我的正则表达式代码在随机输出 "true"、"false" 和 "true",让我感到十分困惑。谢谢! - adriendenat
15
我认为这是更好的答案。它解释了它们不会产生相同的结果并且reg.test()存在一个危险的陷阱。对我来说,这使得string.match()成为明显的选择。对于我来说,性能从来都不是一个问题。 - James
9
很重要!我已经疯了,试图弄清楚为什么每隔一段时间就会失踪一个结果...供其他发现此问题的人参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex - Dan
4
如果你和我当时一样困惑,可以查看https://dev59.com/gnI_5IYBdhLWcg3wHfOr。另外还有[String.prototype.search()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search),它返回一个索引,但据我所知没有这个问题。 - Nateowami
3
只是好奇,为什么要为 .test() 设置全局标志?.test() 的目的不就是检查字符串是否与正则表达式匹配吗? - buhbang
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接