regex.test VS string.match, чтобы узнать, соответствует ли строка регулярному выражению

287

Много раз я использую строковую matchфункцию, чтобы узнать, соответствует ли строка регулярному выражению.

if(str.match(/{regex}/))

Есть ли разница между этим:

if (/{regex}/.test(str))

Кажется, они дают одинаковый результат?

Гдорон поддерживает Монику
источник
4
это лучшие тесты, которые вы найдете jsperf.com/regexp-test-vs-match-m5
ajax333221
@ ajax333221. Спасибо за jsperf, но я не уверен, что это хорошо. Соответствие регулярному выражению с использованием группы соответствия, которая не требуется при поиске логического значения.
Гдорон поддерживает Монику

Ответы:

440

Основное использование

Во-первых, давайте посмотрим, что делает каждая функция:

regexObject . тест ( строка )

Выполняет поиск соответствия между регулярным выражением и указанной строкой. Возвращает истину или ложь .

строка . матч ( RegExp )

Используется для получения совпадений при сопоставлении строки с регулярным выражением. Возвращает массив с совпадениями или, nullесли их нет.

Так как nullоценивает false,

if ( string.match(regex) ) {
  // There was a match.
} else {
  // No match.
} 

Производительность

Есть ли разница в производительности?

Да . Я нашел эту короткую заметку на сайте MDN :

Если вам нужно узнать, соответствует ли строка регулярному выражению regexp, используйте regexp.test (string).

Разница значительна?

Ответ еще раз - ДА ! Этот jsPerf, который я собрал, показывает разницу ~ 30% - ~ 60% в зависимости от браузера:

тест против матча |  Тест производительности

Вывод

Используйте, .testесли вам нужна более быстрая логическая проверка. Используется .matchдля получения всех совпадений при использовании gглобального флага.

Гдорон поддерживает Монику
источник
5
Не слишком удивлен, поскольку строковая функция должна перевернуть вещи и затем создать массив, если есть совпадение. Похоже, я буду продолжать использовать .test(). :)
22
Мои два цента: производительность переоценена. Любой из этих вариантов может выполнить ~ 15 000 операций за одно мгновение на мониторе, поэтому, если вы не выполняете массовое регулярное выражение на стороне клиента, скорость не имеет значения. Конечно, «test» - логически правильная функция, если логический результат - то, что вам нужно. Спасибо за Q / A Кстати.
Дэвид Гилбертсон
2
Интересно, что тестирование на 41% медленнее, чем сравнение для меня с использованием теста jsPerf, описанного выше (Chrome 41, OSX).
Бенджи
1
@AlexShilman indexOf быстрее (но не намного), чем тестирование в соответствии с этим stackoverflow.com/questions/183496/… (можно ожидать, что оно будет быстрее).
Подличник
1
Одна вещь, которая может укусить вас здесь (это недавно укусило мою команду): если вы используете флаг 'g' на своем Regex и создаете новый экземпляр (то есть через новый RegExp (<regex_str>, 'g')), и вы используете его повторно Например, запуск «теста» является состоянием, то есть будет возвращать разные результаты при многократном запуске. См. Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… для получения подробной информации.
Давертрон
118

Не забудьте учесть глобальный флаг в вашем регулярном выражении:

var reg = /abc/g;
!!'abcdefghi'.match(reg); // => true
!!'abcdefghi'.match(reg); // => true
reg.test('abcdefghi');    // => true
reg.test('abcdefghi');    // => false <=

Это потому, что Regexp отслеживает lastIndex при обнаружении нового совпадения.

gtournie
источник
21
Я просто бился в голову, видя, что мой regex.test () случайно записывает в журнал «true», затем «false», а затем «true» ... спасибо!
adriendenat
7
Я думаю, что это лучший ответ. Это объясняет, что они не дают тот же результат, и что reg.test () имеет опасную ловушку. Для меня это делает string.match () очевидным выбором. Производительность никогда не была для меня проблемой.
Джеймс
2
Это важно! Схожу с ума, пытаясь выяснить, почему все остальные результаты отсутствовали ... для справки о ком-либо, кто найдет это: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Дан
2
Если вы так же растеряны, как и я, см. Stackoverflow.com/q/1520800/3714913 . Есть также String.prototype.search () , который возвращает индекс, но, насколько я могу судить, такой проблемы нет.
Nateowami
3
Просто интересно, зачем нужен глобальный флаг .test()? Не стоит ли .test()проверять, имеет ли строка соответствующее регулярное выражение?
Buhbang
0

Это мои результаты теста результаты тестов

тест 4267740 операций в секунду ± 1,32% (60 проб выборки)

Exec 3649719 операций в секунду ± 2,51% (60 проб выборки)

соответствует 3623125 операций в секунду ± 1,85% (62 запускаемых выборки)

indexOf 6230325 операций в секунду ± 0,95% (62 прогона выборки)

метод test быстрее метода match, но самый быстрый метод - indexOf

Рамиль Шавалеев
источник
indexOf не работает с регулярными выражениями, поэтому совершенно не имеет значения.
Гдорон поддерживает Монику