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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4757438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 13:57:06  来源:igfitidea点击:

JavaScript: indexOf vs. Match when Searching Strings?

javascriptregexstringclient

提问by indra

Readability aside, are there any discernable differences (performance perhaps) between using

除了可读性之外,使用之间是否有任何可辨别的差异(可能是性能)

str.indexOf("src") 

and

str.match(/src/)

I personally prefer match(and regexp) but colleagues seem to go the other way. We were wondering if it mattered ...?

我个人更喜欢match(和正则表达式),但同事们似乎反其道而行之。我们想知道这是否重要......?

EDIT:

编辑:

I should have said at the outset that this is for functions that will be doing partial plain-string matching (to pick up identifiers in class attributes for JQuery) rather than full regexp searches with wildcards etc.

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

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

So its the difference between:

所以它的区别在于:

string.indexOf('DisablesGuiClass-');

VS

VS

string.match(/DisablesGuiClass-/)

采纳答案by David Tang

RegExp is indeed slower than indexOf (you can see it here), though normally this shouldn't be an issue. With RegExp, you also have to make sure the string is properly escaped, which is an extra thing to think about.

RegExp 确实比 indexOf 慢(你可以在这里看到它),但通常这不应该是一个问题。使用 RegExp,您还必须确保正确转义字符串,这是需要考虑的额外事项。

Both of those issues aside, if two tools do exactly what you need them to, why not choose the simpler one?

撇开这两个问题不谈,如果两个工具完全满足您的需求,为什么不选择更简单的一个呢?

回答by Tim Pietzcker

Your comparison may not be entirely fair. indexOfis used with plain strings and is therefore very fast; matchtakes a regular expression - of course it may be slower in comparison, but if you want to do a regex match, you won't get far with indexOf. On the other hand, regular expression engines can be optimized, and have been improving in performance in the last years.

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

In your case, where you're looking for a verbatim string, indexOfshould be sufficient. There is still one application for regexes, though: If you need to match entirewords and want to avoid matching substrings, then regular expressions give you "word boundary anchors". For example:

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

indexOf('bar')

will find barthree times in bar, fubar, barmy, whereas

将在 中找到bar3 次bar, fubar, barmy,而

match(/\bbar\b/)

will only match barwhen it is not part of a longer word.

只有bar当它不是较长单词的一部分时才会匹配。

As you can see in the comments, some comparisons have been done that show that a regex may be faster than indexOf- if it's performance-critical, you may need to profile your code.

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

回答by Yogesh Mangaj

If you're trying to search for substring occurrences case-insensitivelythen matchseems to be faster than a combination of indexOfand toLowerCase()

如果你想搜索的子串出现不区分大小写然后match似乎是比快的组合indexOftoLowerCase()

Check here - http://jsperf.com/regexp-vs-indexof/152

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

回答by Mohamed Allal

Here all possible ways (relatively) to search for string

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

// 1. includes (introduced in ES6)

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

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

// 2. string.indexOf

// 2. string.indexOf

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

// 3. RegExp: test

// 3. 正则表达式:测试

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

// 4. string.match

// 4. 字符串匹配

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

//5. string.search

//5. 字符串搜索

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

Here a src: https://koukia.ca/top-6-ways-to-search-for-a-string-in-javascript-and-performance-benchmarks-ce3e9b81ad31

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

Benchmarks seem to be twisted specially for es6 includes , read the comments.

基准似乎是专门为 es6 includes 扭曲的,请阅读评论。

In resume:

在简历中:

if you don't need the matches. => Either you need regex and so use test. Otherwise es6 includesor indexOf. Still testvs indexOfare close.

如果你不需要火柴。=> 要么你需要正则表达式,所以使用test。否则 es6包含indexOf。仍然测试indexOf接近。

And for includes vs indexOf:

对于包含与 indexOf:

They seem to be the same : https://jsperf.com/array-indexof-vs-includes/4(if it was different it would be wierd, they mostly perform the same except for the differences that they expose check this)

它们似乎是相同的:https: //jsperf.com/array-indexof-vs-includes/4(如果不同,那就很奇怪了,除了它们公开的差异之外,它们的性能大多相同,请检查此内容

And for my own benchmark test. here it is http://jsben.ch/fFnA0You can test it (it's browser dependent) [test multiple time] here how it performed (multiple run indexOf and includes one beat the other, and they are close). So they are the same. [here using the same test platform as the article above].

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

enter image description hereenter image description here

在此处输入图片说明在此处输入图片说明

And here for the a long text version (8 times longer) http://jsben.ch/wSBA2

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

enter image description here

在此处输入图片说明

Tested both chrome and firefox, same thing.

测试了chrome和firefox,同样的事情。

Notice jsben.ch doesn't handle memory overflow (or there limits correctly. It doesn't show any message) so result can get wrong if you add more then 8 text duplication (8 work well). But the conclusion is for very big text all three perform the same way. Otherwise for short indexOf and includes are the same and test a little bit slower. or Can be the same as it seemed in chrome (firefox 60 it is slower).

请注意 jsben.ch 不处理内存溢出(或正确限制。它不显示任何消息),因此如果添加超过 8 个文本重复(8 个工作良好),结果可能会出错。但结论是对于非常大的文本,所有三个都以相同的方式执行。否则对于简短的 indexOf 和包含是相同的,并且测试速度会慢一点。或 可以与在 chrome 中看起来相同(firefox 60 更慢)。

Notice with jsben.ch: don't freak out if you get inconsistant result. Try different time and see if it's consistent or not. Change browser, sometimes they just run totally wrong. Bug or bad handling of memory. Or something.

请注意 jsben.ch:如果您得到不一致的结果,请不要惊慌。尝试不同的时间,看看它是否一致。更换浏览器,有时他们只是运行完全错误。错误或内存处理不当。或者其他的东西。

ex:

前任:

enter image description here

在此处输入图片说明

Here too my benchmark on jsperf (better details, and handle graphs for multiple browsers)

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

(top is chrome)

(顶部是镀铬)

normal texthttps://jsperf.com/indexof-vs-includes-vs-test-2019
resume:includes and indexOf have same perofrmance. test slower.

普通文本https://jsperf.com/indexof-vs-includes-vs-test-2019
简历:includes 和 indexOf 具有相同的性能。测试比较慢。

enter image description hereenter image description here(seem all three perform the same in chrom)

在此处输入图片说明在此处输入图片说明(似乎所有三个在 chrom 中的表现都一样)

Long text(12 time longer then normal) https://jsperf.com/indexof-vs-includes-vs-test-2019-long-text-str/
resume:All the three perform the same. (chrome and firefox) enter image description here

长文本(比普通文本长12 倍) https://jsperf.com/indexof-vs-includes-vs-test-2019-long-text-str/
resume:三者的表现相同。(铬和火狐) 在此处输入图片说明

very short stringhttps://jsperf.com/indexof-vs-includes-vs-test-2019-too-short-string/
resume:includes and indexOf perform the same and test slower.

非常短的字符串https://jsperf.com/indexof-vs-includes-vs-test-2019-too-short-string/
resume:includes 和 indexOf 执行相同但测试速度较慢。

enter image description here

在此处输入图片说明

Note: about the benchmark above. For the very short stringversion (jsperf) had an big error for chrome. Seeing by my eyes. around 60 sample was run for both indexOf and includes same way (repeated a lot of time). And test a little bit less and so slower. don't be fooled with the wrong graph. It's clear wrong. Same test work ok for firefox, surely it's a bug.

注意:关于上面的基准。对于非常短的字符串版本(jsperf),chrome 有一个很大的错误。亲眼所见。为 indexOf 运行了大约 60 个样本,并包括相同的方式(重复了很多时间)。并测试少一点,所以更慢。不要被错误的图表所迷惑。很明显错了。Firefox 的测试工作正常,当然这是一个错误。

Here the illustration: (the first image was the test on firefox) enter image description herewaaaa. Suddenly indexOf became superman. But as i said i did the test, and looked at the number of samples it was around 60. Both indexOf and includes and they performed the same. A bug on jspref. Except for this one (maybe because of a memory restriction related problem) all the rest was consistent, it give more details. And you see how many simple happen in real time.

这是插图:(第一张图片是在 Firefox 上的测试) 在此处输入图片说明waaaa。突然 indexOf 变成了超人。但正如我所说,我做了测试,并查看了大约 60 个样本的数量。 indexOf 和包括它们的表现都是一样的。jspref上的一个错误。除了这个(可能是因为内存限制相关的问题),其余的都是一致的,它提供了更多的细节。你会看到有多少简单的事情实时发生。

Final resume

最终简历

indexOf vs includes=> Same performance

indexOf 与包含=> 相同的性能

test=> can be slower for short strings or text. And the same for long texts. And it make sense for the overhead that the regex engine add. In chrome it seemed it doesn't matter at all.

test=> 对于短字符串或文本可能会更慢。对于长文本也是如此。这对于正则表达式引擎添加的开销是有意义的。在 chrome 中,它似乎根本无关紧要。

回答by elreimundo

You ask whether str.indexOf('target')or str.match(/target/)should be preferred. As other posters have suggested, the use cases and return types of these methods are different. The first asks "where in strcan I first find 'target'?" The second asks "does strmatch the regex and, if so, what are all of the matches for any associated capture groups?"

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

The issue is that neither one technically is designed to ask the simpler question "does the string contain the substring?" There is something that is explicitly designed to do so:

问题在于,从技术上讲,没有一个人旨在提出更简单的问题“字符串是否包含子字符串?” 有一些东西是明确设计的:

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

There are several advantages to using regex.test(string):

使用 有几个优点regex.test(string)

  1. It returns a boolean, which is what you care about
  2. It is more performant than str.match(/target/)(and rivals str.indexOf('target'))
  3. If for some reason, stris undefinedor null, you'll get false(the desired result) instead of throwing a TypeError
  1. 它返回一个布尔值,这是你关心的
  2. 它比str.match(/target/)(和竞争对手str.indexOf('target'))性能更高
  3. 如果由于某种原因strundefinednull,您将获得false(所需的结果)而不是抛出TypeError

回答by LukeH

Using indexOfshould, in theory, be faster than a regex when you're just searching for some plain text, but you should do some comparative benchmarks yourself if you're concerned about performance.

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

If you prefer matchand it's fast enough for your needs then go for it.

如果您愿意,match并且它的速度足以满足您的需求,那就去吧。

For what it's worth, I agree with your colleagues on this: I'd use indexOfwhen searching for a plain string, and use matchetc only when I need the extra functionality provided by regular expressions.

就其价值而言,我同意您的同事的看法:我会indexOf在搜索纯字符串时使用,match仅在需要正则表达式提供的额外功能时才使用etc。

回答by ChaosPandion

Performance wise indexOfwill at the very least be slightly faster than match. It all comes down to the specific implementation. When deciding which to use ask yourself the following question:

性能方面indexOf至少会比match. 这一切都归结为具体的实现。在决定使用哪个时,问自己以下问题:

Will an integer index suffice or do I need the functionality of a RegExp match result?

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

回答by gfullam

The return values are different

返回值不同

Aside from the performance implications, which are addressed by other answers, it is important to note that the return values for each method are different; so the methods cannot merely be substituted without also changing your logic.

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

Return value of .indexOf: integer

的返回值.indexOfinteger

The index within the calling Stringobject of the first occurrence of the specified value, starting the search at fromIndex.
Returns -1if the value is not found.

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

Return value of .match: array

的返回值.matcharray

An Array containing the entire match result and any parentheses-captured matched results.
Returns nullif there were no matches.

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

Because .indexOfreturns 0if the calling string beginswith the specified value, a simple truthy test will fail.

因为如果调用字符串指定值开头.indexOf返回,所以简单的真实测试将失败。0

For example:

例如:

Given this class…

鉴于这门课…

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

…the return values for each would differ:

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

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

The correct way to run a truthy test with the return from .indexOfis to test against -1:

运行带有返回值的真实测试的正确方法.indexOf是针对 进行测试-1

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

回答by NoWomenNoCry

remember Internet Explorer 8 doesnt understand indexOf. But if nobody of your users uses ie8 (google analytics would tell you) than omit this answer. possible solution to fix ie8: How to fix Array indexOf() in JavaScript for Internet Explorer browsers

记得 Internet Explorer 8 不明白indexOf。但是,如果您的用户中没有人使用 ie8(谷歌分析会告诉您),请忽略此答案。修复 ie8 的可能解决方案: How to fix Array indexOf() in JavaScript for Internet Explorer Browser