JavaScript: indexOf vs. Match podczas wyszukiwania ciągów?

Pomijając czytelność, czy istnieją jakieś dostrzegalne różnice (być może wydajność) między używaniem

str.indexOf("src") 

I

str.match(/src/)

Ja osobiście wolę match (i regexp), ale koledzy zdają się iść w drugą stronę. Zastanawialiśmy się, czy to ma znaczenie ...?

EDIT:

Powinienem powiedzieć na początku, że jest to dla funkcji, które będą wykonywać częściowe dopasowanie zwykłego ciągu znaków (aby odebrać identyfikatory w atrybutach klasy dla JQuery), a nie Pełne wyszukiwanie regexp z dzikimi kartami itp.

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

Więc jest różnica między:

string.indexOf('DisablesGuiClass-');

I

string.match(/DisablesGuiClass-/)
Author: Denis Howe, 2011-01-21

9 answers

RegExp jest rzeczywiście wolniejszy niż indexOf (możesz go zobaczyć tutaj), chociaż normalnie nie powinno to być problemem. Z RegExp, musisz również upewnić się, że ciąg znaków jest poprawnie unikalny, co jest dodatkową rzeczą do przemyślenia.

Obie te kwestie na bok, jeśli dwa narzędzia robią dokładnie to, czego potrzebujesz, dlaczego nie wybrać prostszego?

 61
Author: David Tang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-21 10:06:58

Twoje porównanie może nie być do końca uczciwe. indexOf jest używany z prostymi łańcuchami i dlatego jest bardzo szybki; match przyjmuje Wyrażenie regularne - oczywiście może być wolniejsze w porównaniu, ale jeśli chcesz dopasować regex, nie zajdziesz daleko z indexOf. Z drugiej strony, silniki wyrażeń regularnych mogą być zoptymalizowane i poprawiają wydajność w ostatnich latach.

W Twoim przypadku, gdzie szukasz ciągu słownego, indexOf powinno wystarczyć. Jest jeszcze jeden aplikacja dla wyrażeń regularnych: jeśli chcesz dopasować całe słowa i chcesz uniknąć dopasowania podciągów, wtedy wyrażenia regularne dają Ci "kotwice graniczne słowa". Na przykład:

indexOf('bar')

Znajdzie bar trzy razy w bar, fubar, barmy, natomiast

match(/\bbar\b/)

Będzie pasować bar tylko wtedy, gdy nie jest częścią dłuższego słowa.

Jak widać w komentarzach, dokonano pewnych porównań, które pokazują, że regex może być szybszy niż indexOf - jeśli ma kluczowe znaczenie dla wydajności, możesz może być konieczne profilowanie kodu.

 19
Author: Tim Pietzcker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-29 07:46:42

Tutaj wszystkie możliwe sposoby (względnie) wyszukiwania ciągu

// 1. includes (introduced in ES6)

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

// 2. sznurek.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. sznurek.match

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

//5. sznurek.Szukaj

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

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

Benchmarki wydają się być skręcone specjalnie dla ES6 includes, przeczytaj komentarze.

W CV:

Jeśli nie potrzebujesz zapałek. = > Albo potrzebujesz regex i dlatego użyj test. W przeciwnym razie es6 zawiera lub indexOf. Wciąż test vs indeks są blisko.

I dla includes vs indexOf:

Wydają się być takie same: https://jsperf.com/array-indexof-vs-includes/4 (gdyby było inaczej to byłoby dziwne, w większości wykonują to samo z wyjątkiem różnic, które expose check this )

I dla mojego własnego testu porównawczego. tutaj jest http://jsben.ch/fFnA0 Możesz go przetestować (zależy od przeglądarki) [testuj wielokrotnie] tutaj Jak to wykonało (wiele uruchomień indexOf i zawiera jeden beat drugi, i są one blisko). Więc są takie same. [tutaj przy użyciu tej samej platformy testowej, co artykuł powyżej].

Tutaj wpisz opis obrazka Tutaj wpisz opis obrazka

I tutaj dla długiej wersji tekstu (8 razy dłużej) http://jsben.ch/wSBA2

Tutaj wpisz opis obrazka

Testowałem chrome i Firefoksa, to samo.

Zawiadomienie jsben.ch nie obsługuje przepełnienia pamięci (lub nie ma ograniczeń poprawnie. Nie pokazuje żadnej wiadomości) więc wynik może się pomylić, jeśli dodasz więcej niż 8 duplikacji tekstu (8 działa dobrze). Ale wniosek jest taki, że dla bardzo dużego tekstu wszystkie trzy działają w ten sam sposób. W przeciwnym razie dla krótkiego indexOf i includes są takie same i testują trochę wolniej. lub może być taka sama jak się wydawało w chrome (firefox 60 jest wolniejszy).

Zawiadomienie z jsben.ch: nie świruj, jeśli uzyskasz niespójny wynik. Spróbuj o innej porze i sprawdź, czy jest spójna, czy nie. Zmień przeglądarkę, czasami po prostu działają całkowicie źle. Błąd lub złe obchodzenie się z pamięcią. Czy coś.

Ex:

Tutaj wpisz opis obrazka

Tutaj też mój benchmark na jsperf (lepsze szczegóły i obsługa wykresów dla wielu przeglądarek)

(góra jest chromowana)

Normal tekst https://jsperf.com/indexof-vs-includes-vs-test-2019
resume: includes i indexOf mają taką samą perefrmancję. testuj wolniej.

Tutaj wpisz opis obrazka Tutaj wpisz opis obrazka (wszystkie trzy wykonują to samo w chromie)

Długi tekst (12 razy dłuższy niż normalny) https://jsperf.com/indexof-vs-includes-vs-test-2019-long-text-str/
resume: wszystkie trzy wykonują to samo. (chrom i firefox) Tutaj wpisz opis obrazka

Bardzo krótki sznurek https://jsperf.com/indexof-vs-includes-vs-test-2019-too-short-string/
resume: includes i indexOf wykonują to samo i testują wolniej.

Tutaj wpisz opis obrazka

Uwaga: o benchmarku powyżej. W wersji Bardzo krótki ciąg (jsperf) miał duży błąd dla chrome. Widzieć moimi oczami. około 60 prób przeprowadzono dla obu indexOf i zawiera w ten sam sposób (powtórzył wiele czas). I testować trochę mniej i tak wolniej. nie daj się zwieść z niewłaściwym wykresem. To oczywiste. Ta sama praca testowa ok dla Firefoksa, na pewno jest to błąd.

Tutaj ilustracja: (pierwszy obrazek był testem na Firefoksie) Tutaj wpisz opis obrazka waaaa. Nagle indexOf stał się Supermanem. Ale jak powiedziałem, zrobiłem test, i spojrzał na liczbę próbek było około 60. Zarówno indexOf jak i includes wykonali to samo. Błąd na jspref . Oprócz tego (może dlatego, że problem związany z ograniczeniem pamięci) cała reszta była spójna, podaje więcej szczegółów. I widzisz, jak wiele prostych dzieje się w czasie rzeczywistym.

Ostatnie wznowienie

IndexOf vs includes = > Same performance

Test = > Może być wolniejszy dla krótkich łańcuchów lub tekstu. I to samo w przypadku długich tekstów. I to ma sens dla napowietrznych, które dodaje silnik regex. W chrome wydawało się, że to nie ma znaczenia.

 13
Author: Mohamed Allal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-05 16:32:49

Jeśli próbujesz wyszukać podcięcia niezależnie od wielkości liter, match wydaje się być szybsze niż kombinacja indexOf i toLowerCase()

Sprawdź tutaj - http://jsperf.com/regexp-vs-indexof/152

 11
Author: Yogesh Mangaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 12:54:13

Pytasz, czy str.indexOf('target') lub str.match(/target/) powinny być preferowane. Jak sugerowały inne plakaty, przypadki użycia i typy zwrotów tych metod są różne. Pierwszy pyta " gdzie w str mogę najpierw znaleźć 'target'?"Drugie pytanie" czy str pasuje do wyrażenia regularnego, a jeśli tak, to jakie są wszystkie dopasowania dla powiązanych grup przechwytywania?"

Problem polega na tym, że żaden z nich technicznie nie jest przeznaczony do zadawania prostszego pytania " czy łańcuch zawiera podłańcuch?"Jest coś, co jest wprost zaprojektowane do tego:

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

Istnieje kilka zalet korzystania z regex.test(string):

  1. Zwraca wartość logiczną, na której ci zależy
  2. jest bardziej wydajny niż str.match(/target/) (i rywale str.indexOf('target'))
  3. Jeśli z jakiegoś powodu str jest undefined lub null, otrzymasz false (pożądany wynik) zamiast rzucać TypeError
 6
Author: elreimundo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 18:16:13

Użycie indexOf powinno teoretycznie być szybsze niż wyrażenie regularne, gdy szukasz zwykłego tekstu, ale powinieneś zrobić kilka porównawczych benchmarków samodzielnie, jeśli martwisz się o wydajność.

Jeśli wolisz match i jest wystarczająco szybki dla Twoich potrzeb, to idź na to.

Jeśli to coś warte, zgadzam się z twoimi kolegami w tej sprawie: użyłbym indexOf podczas wyszukiwania zwykłego ciągu, A używać match itp tylko wtedy, gdy potrzebuję dodatkowej funkcjonalności zapewnianej przez zwykłe wyrażenia.

 5
Author: LukeH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-21 10:02:44

Sprawność indexOf będzie co najmniej nieco szybsza niż match. Wszystko sprowadza się do konkretnego wdrożenia. Decydując się na użycie zadaj sobie następujące pytanie:

Czy wystarczy indeks integer czy potrzebujesz funkcjonalności wyrażenia regularnego wynik meczu?

 4
Author: ChaosPandion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-21 10:05:21

Wartości zwracane są różne

Oprócz implikacji wydajności, które są rozwiązywane przez inne odpowiedzi, ważne jest, aby zauważyć, że wartości zwracane dla każdej metody są różne; więc metody nie mogą być jedynie zastępowane bez zmiany logiki.

Return value of .indexOf: integer

Indeks wewnątrz obiektu wywołującego String pierwszego wystąpienia określonej wartości, rozpoczynającego wyszukiwanie w fromIndex.
zwraca -1 Jeśli wartość nie została znaleziona.

Return value of .match: array

Tablica zawierająca cały wynik meczu i wszelkie nawiasy-przechwycone dopasowane wyniki.
zwraca null jeśli nie było dopasowania .

Ponieważ .indexOf zwraca 0 jeśli łańcuch wywołujący zaczyna się z podaną wartością, prosty test prawdziwości nie powiedzie się.

Na przykład:

biorąc pod uwagę tę klasę ...

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

...wartości zwracane dla każdego będą się różnić:

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

Prawidłowym sposobem przeprowadzenia testu z powrotem z .indexOf jest sprawdzenie z -1:

if (string.indexOf('DisablesGuiClass-') !== -1) {
//  ^returns `0`                        ^evaluates to `true`
    … // this block is run.
}
 3
Author: gfullam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Pamiętaj Internet Explorer 8 nie rozumie indexOf. Ale jeśli nikt z Twoich użytkowników nie korzysta z ie8 (Google analytics powie Ci), pomiń tę odpowiedź. możliwe rozwiązanie do naprawy ie8: Jak naprawić Array indexOf () w JavaScript dla przeglądarek Internet Explorer

 -1
Author: NoWomenNoCry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:05