JavaScript:indexOf与搜索字符串时匹配?

时间:2011-01-21 09:59:09

标签: javascript regex string client

除了可读性之外,使用

之间是否存在任何可辨别的差异(可能性能)
str.indexOf("src") 

str.match(/src/)

我个人更喜欢match(和regexp),但同事似乎走了另一条道路。我们想知道它是否重要......?

编辑:

我应该在一开始就说过,这是为了进行部分普通字符串匹配的函数(在JQuery的类属性中选择标识符),而不是使用通配符等进行完整的正则表达式搜索。

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

所以它的区别在于:

string.indexOf('DisablesGuiClass-');

VS

string.match(/DisablesGuiClass-/)

10 个答案:

答案 0 :(得分:53)

RegExp确实比indexOf慢(你可以看到它here),虽然通常这应该不是问题。使用RegExp,您还必须确保正确转义字符串,这是一个值得思考的额外内容。

除了这两个问题之外,如果两个工具完全符合您的需求,为什么不选择更简单的工具呢?

答案 1 :(得分:19)

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

在您的情况下,如果您要查找逐字字符串,indexOf就足够了。但是仍然有一个正则表达式的应用程序:如果你需要匹配整个单词并希望避免匹配子字符串,那么正则表达式会给你“单词边界锚点”。例如:

indexOf('bar')

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

match(/\bbar\b/)

仅当bar不属于较长的单词时才会匹配。

正如您在评论中所看到的,已经进行了一些比较,表明正则表达式可能比indexOf更快 - 如果它的性能至关重要,您可能需要对代码进行概要分析。

答案 2 :(得分:8)

如果您尝试搜索子字符串出现不区分大小写,那么match似乎比indexOftoLowerCase()的组合更快

点击此处 - http://jsperf.com/regexp-vs-indexof/152

答案 3 :(得分:6)

您是否应该首选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 < / LI>

答案 4 :(得分:5)

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

如果您更喜欢match并且它足够快以满足您的需求,那就去吧。

对于它的价值,我同意你的同事:我在搜索普通字符串时使用indexOf,并且仅当我需要常规提供的额外功能时才使用match等表达式。

答案 5 :(得分:4)

明智的表现indexOf至少会比match略快。这一切都归结为具体实施。在决定使用哪个问题时,请问自己以下问题:

  

整数索引是否足够或是我   需要RegExp的功能   匹配结果?

答案 6 :(得分:3)

返回值不同

除了其他答案所解决的性能影响之外,重要的是要注意每种方法的返回值是不同的;所以这些方法不能仅仅在不改变你的逻辑的情况下被替换。

.indexOf的返回值:integer

  

第一次出现指定值的调用String对象中的索引,从fromIndex开始搜索。
如果值为,则返回-1找不到。

.match的返回值:array

  

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

如果.indexOf返回0,如果调用字符串以指定值开始,则简单的真理测试将失败。

例如:

鉴于此课程......

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

...每个的返回值会有所不同:

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

VS

//  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.
}

答案 7 :(得分:2)

有所有可能的方式来搜索字符串

// 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:测试

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 includes扭曲,请阅读注释。

在简历中:

如果您不需要匹配项。 =>要么需要正则表达式,然后使用 test 。否则,es6 包括 indexOf 。仍然测试 indexOf 接近。

对于包括vs indexOf:

它们似乎是相同的:https://jsperf.com/array-indexof-vs-includes/4(如果不同,那会很奇怪,除了表现出check this的差异外,它们的性能基本相同)

并进行我自己的基准测试。这是http://jsben.ch/fFnA0 您可以对其进行测试(取决于浏览器)[多次测试] 此处的效果如何(多次运行indexOf并包含一个击败另一个,并且它们很接近)。所以他们是一样的。 [此处使用与以上文章相同的测试平台]。

enter image description here enter image description here

这里是长文本版本(长8倍) http://jsben.ch/wSBA2

enter image description here

同时测试了chrome和Firefox。

注意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浏览器存在较大错误。以我的眼神来看。两个indexOf都运行了大约60个样本,并且包含相同的方式(重复了很多次)。并测试得少一点,那么慢。 不要被错误的图表所迷惑。显然是错误的。对于Firefox,相同的测试工作还可以,当然这是一个错误。

这里是插图:(第一个图像是对Firefox的测试) enter image description here 哇啊。突然indexOf成为超人。但是正如我所说,我做了测试,并查看了大约60个样本。indexOf和include以及它们执行的都是相同的。 jspref 上的错误。除了这一点(可能是由于与内存限制有关的问题)之外,其余所有内容都是一致的,它提供了更多细节。您会实时看到多少简单的事情。

最终简历

indexOf vs包含 =>效果相同

测试 =>对于短字符串或文本,可能会变慢。与长文本相同。对于正则表达式引擎增加的开销,这是有意义的。在Chrome中,这似乎没有任何关系。

答案 8 :(得分:0)

只有在您真正需要时才会使用indexOf来存在子串和match。即如果您在一个也可能包含src的字符串中搜索单词 altsrc,那么aString.match(/\bsrc\b/)确实更合适。

答案 9 :(得分:0)

请记住,Internet Explorer 8并不理解indexOf。 但是,如果您的用户中没有人使用ie8(谷歌分析会告诉你),而不是省略这个答案。 修复ie8的可能解决方案: How to fix Array indexOf() in JavaScript for Internet Explorer browsers