当搜索字符串时 indexOf 与 Match?

除了可读性之外,使用

str.indexOf("src")

还有

str.match(/src/)

我个人更喜欢 match(和 regexp) ,但同事们似乎反其道而行之。我们想知道这有没有关系?

编辑:

我应该在一开始就说明,这是针对那些将执行部分纯字符串匹配(在类属性中为 JQuery 提取标识符)的函数,而不是使用通配符等进行完整的 regexp 搜索的函数。

class='redBorder DisablesGuiClass-2345-2d73-83hf-8293'

这就是两者的区别:

string.indexOf('DisablesGuiClass-');

还有

string.match(/DisablesGuiClass-/)
72304 次浏览

在理论上,当您只是搜索一些纯文本时,使用 indexOf应该比使用正则表达式快,但是如果您关心性能,那么您应该自己做一些比较基准测试。

如果你喜欢 match,它的速度足够快,你的需要,然后去。

值得一提的是,我同意你的同事的观点: 我会在搜索纯字符串时使用 indexOf,只有当我需要正则表达式提供的额外功能时才使用 match等。

性能方面,indexOf至少比 match稍微快一点。这一切都取决于具体的实现。在决定使用哪种方法时,问自己以下问题:

一个整数索引就足够了吗 需要 RegExp 的功能 比赛结果如何?

你的比较可能不完全公平。indexOf与普通字符串一起使用,因此非常快; match采用正则表达式——当然,相比之下它可能会慢一些,但是如果您想进行正则表达式匹配,那么使用 indexOf就走不远。另一方面,正则表达式引擎可以进行优化,并且在过去几年中性能一直在提高。

在您的示例中,如果要查找逐字字符串,那么 indexOf应该足够了。不过,正则表达式还有一个应用程序: 如果您需要匹配 完整的单词,并且希望避免匹配子字符串,那么正则表达式将为您提供“单词边界锚”。例如:

indexOf('bar')

会在 bar, fubar, barmy中找到 bar三次,而

match(/\bbar\b/)

将只匹配 bar时,它不是一个较长的字的一部分。

正如您在注释中看到的,已经进行了一些比较,表明正则表达式可能比 indexOf快-如果它的性能关键,您可能需要分析您的代码。

RegExp 的确比 indexOf 慢(可以看到它是 给你) ,不过通常这不是问题。对于 RegExp,还必须确保字符串被正确转义,这是需要考虑的另一个问题。

抛开这两个问题不谈,如果有两个工具可以完成您需要它们完成的任务,为什么不选择更简单的一个呢?

如果您试图搜索子串出现 粗心大意地,那么 match似乎比 indexOftoLowerCase()的组合更快

检查这里-http://jsperf.com/regexp-vs-indexof/152

返回值是不同的

除了由其他答案解决的性能影响之外,重要的是要注意每个方法的返回值是不同的; 因此不能仅仅替换方法而不改变逻辑。

返回值 .indexOf: integer

调用 String对象中指定值的第一个匹配项的索引,从 fromIndex开始搜索。如果没有找到值,返回 -1

返回值 .match: array

包含整个匹配结果和任何括号捕获的匹配结果的数组。 < br/> 如果没有匹配,返回 null

因为如果调用字符串 开始具有指定的值,则 .indexOf返回 0,所以一个简单的真值测试将失败。

例如:

鉴于这门课..。

class='DisablesGuiClass-2345-2d73-83hf-8293 redBorder'

... 每种方法的回报率都不同:

//  returns `0`, evaluates to `false`
if (string.indexOf('DisablesGuiClass-')) {
… // this block is skipped.
}

对。

//  returns `["DisablesGuiClass-"]`, evaluates to `true`
if (string.match(/DisablesGuiClass-/)) {
… // this block is run.
}

使用从 .indexOf返回的结果运行真实性测试的正确方法是针对 -1进行测试:

if (string.indexOf('DisablesGuiClass-') !== -1) {
//  ^returns `0`                        ^evaluates to `true`
… // this block is run.
}

你问 str.indexOf('target')还是 str.match(/target/)应该是首选。正如其他海报所建议的,这些方法的用例和返回类型是不同的。第一个问题是“在 str中哪里可以首先找到 'target'?”第二个问题是“ str是否匹配正则表达式,如果匹配,那么所有相关捕获组的匹配项是什么?”

问题在于,从技术上讲,这两个问题都不是为了问一个更简单的问题: “字符串包含子字符串吗?”有一些事情是明确设计来做到这一点的:

var doesStringContainTarget = /target/.test(str);

使用 regex.test(string)有几个好处:

  1. 它返回一个布尔值,这正是您所关心的
  2. 它的性能比 str.match(/target/)(和竞争对手 str.indexOf('target'))
  3. 如果由于某种原因,strundefinednull,那么您将得到 false(期望的结果) ,而不是抛出 TypeError

记住,Internet Explorer 8听不懂。 但是如果你的用户中没有人使用 ie8(谷歌分析会告诉你)而忽略了这个答案。 修复 ie8的可能解决方案: 如何为 Internet Explorer 浏览器修复 JavaScript 中的 Array indexOf ()

这里有搜索字符串的所有可能方法(相对而言)

//1. 包括(在 ES6中引入)

var string = "string to search for substring",
substring = "sea";
string.includes(substring);

//2. string.indexOf

var string = "string to search for substring",
substring = "sea";
string.indexOf(substring) !== -1;

//3. RegExp: test

var string = "string to search for substring",
expr = /sea/;  // no quotes here
expr.test(string);

//4. string.match

var string = "string to search for substring",
expr = "/sea/";
string.match(expr);

//5. string.search

var string = "string to search for substring",
expr = "/sea/";
string.search(expr);

这里有一个 src: https://koukia.ca/top-6-ways-to-search-for-a-string-in-javascript-and-performance-benchmarks-ce3e9b81ad31

基准似乎是专门为 es6包括扭曲,阅读评论。

简历:

如果你不需要火柴的话。 = > 要么需要正则表达式,因此使用 测试。否则,第6季 包括索引测试索引仍然很接近。

以及 for include vs indexOf:

它们看起来是一样的: https://jsperf.com/array-indexof-vs-includes/4(如果它们不同,那就很奇怪了,除了它们暴露出 看看这个的不同之外,它们大多执行相同的操作)

对于我自己的基准测试,这里有一个 http://jsben.ch/ffna0 您可以测试它(它依赖于浏览器)[多次测试] 在这里它是如何执行的(多个运行 indexOf,包括一个击败另一个,他们是接近的)。所以它们是一样的。[在这里使用与上面文章相同的测试平台]。

enter image description here enter image description here

这里是一个长文本版本(8倍长) Http://jsben.ch/wsba2

enter image description here

测试了铬和火狐,结果一样。

注意 jsben.ch 不处理内存溢出(或者正确地存在限制)。它不显示任何消息) ,所以结果可能会错误,如果你添加超过8个文本复制(8工作良好)。但结论是,对于非常大的文本,所有三个执行相同的方式。否则对于短 indexOf 和 include 是相同的,并且测试稍微慢一点。或者可以和在 chrome 中看到的一样(Firefox 60比较慢)。

注意 jsben.ch: 如果得到不一致的结果,不要惊慌失措。试试不同的时间,看看是否一致。改变浏览器,有时他们只是运行完全错误。内存错误或错误处理。或者别的什么。

例如:

enter image description here

这里也是我对 jsperf 的基准测试(更好的细节,并处理多个浏览器的图形)

(上面是铬合金)

正常的短信 Https://jsperf.com/indexof-vs-includes-vs-test-2019
简历: 包括和 indexOf 具有相同的性能。测试较慢。

enter image description here enter image description here (似乎三者在铬合金中表现相同)

长文本 (比正常长12倍) Https://jsperf.com/indexof-vs-includes-vs-test-2019-long-text-str/
简历: 所有三个程序的性能都相同。(chrome 和 firefox)
enter image description here

非常短的绳子 Https://jsperf.com/indexof-vs-includes-vs-test-2019-too-short-string/
履历: 包括和 indexOf 执行相同的操作,测试速度较慢。

enter image description here

注: 关于上述基准。对于 非常短的绳子版本(jsperf)的 chrome 有一个很大的错误。用我的眼睛看。大约60个样本运行的索引和包括相同的方式(重复了很多次)。测试的次数少一点,速度慢一点。 不要被错误的图表所愚弄。这是明显的错误。同样的测试工作可以为 Firefox,肯定是一个错误。

这里的插图: (第一张图片是在 firefox 上的测试) enter image description here 哇。突然变成了超人。但正如我所说,我做了测试,看看样本的数量,大约是60。IndexOf 和 include 以及它们执行相同的操作。Jspref频道有窃听器。除了这一个(可能是因为内存限制相关的问题) ,其余的都是一致的,它给出了更多的细节。你可以看到实时发生了多少简单的事情。

最终简历

IndexOf vs 包括 = > 相同的性能

Test = > 对于短字符串或文本可以慢一些。长短信也一样。对于正则表达式引擎添加的开销来说,这是有意义的。在铬合金中,似乎一点也不重要。