可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 ...?
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.
class='redBorder DisablesGuiClass-2345-2d73-83hf-8293'
So its the difference between:
string.indexOf('DisablesGuiClass-');
VS
string.match(/DisablesGuiClass-/)
回答1:
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.
Both of those issues aside, if two tools do exactly what you need them to, why not choose the simpler one?
回答2:
Your comparison may not be entirely fair. indexOf
is used with plain strings and is therefore very fast; match
takes 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.
In your case, where you're looking for a verbatim string, indexOf
should be sufficient. There is still one application for regexes, though: If you need to match entire words and want to avoid matching substrings, then regular expressions give you "word boundary anchors". For example:
indexOf('bar')
will find bar
three times in bar, fubar, barmy
, whereas
match(/\bbar\b/)
will only match bar
when it is not part of a longer word.
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.
回答3:
If you're trying to search for substring occurrences case-insensitively then match
seems to be faster than a combination of indexOf
and toLowerCase()
Check here - http://jsperf.com/regexp-vs-indexof/152
回答4:
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 str
can I first find 'target'
?" The second asks "does str
match the regex and, if so, what are all of the matches for any associated capture groups?"
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)
:
- It returns a boolean, which is what you care about
- It is more performant than
str.match(/target/)
(and rivals str.indexOf('target')
)
- If for some reason,
str
is undefined
or null
, you'll get false
(the desired result) instead of throwing a TypeError
回答5:
Using indexOf
should, 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.
If you prefer match
and it's fast enough for your needs then go for it.
For what it's worth, I agree with your colleagues on this: I'd use indexOf
when searching for a plain string, and use match
etc only when I need the extra functionality provided by regular expressions.
回答6:
Performance wise indexOf
will 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:
Will an integer index suffice or do I
need the functionality of a RegExp
match result?
回答7:
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
The index within the calling String
object of the first occurrence of the specified value, starting the search at fromIndex
.
Returns -1
if the value is not found.
Return value of .match
: array
An Array containing the entire match result and any parentheses-captured matched results.
Returns null
if there were no matches.
Because .indexOf
returns 0
if the calling string begins with the specified value, a simple truthy test will fail.
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 .indexOf
is to test against -1
:
if (string.indexOf('DisablesGuiClass-') !== -1) {
// ^returns `0` ^evaluates to `true`
… // this block is run.
}
回答8:
always use indexOf
for existence of substrings and match
only when you actually need it. i.e. if you were searching for the word src
in a string that could also contain altsrc
then aString.match(/\bsrc\b/)
is indeed more appropriate.
回答9:
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