regex.test VS string.match pour savoir si une chaîne correspond à une expression régulière

287

Plusieurs fois, j'utilise la matchfonction chaîne pour savoir si une chaîne correspond à une expression régulière.

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

Y a-t-il une différence entre cela:

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

Ils semblent donner le même résultat?

gdoron soutient Monica
la source
4
ce sont les meilleurs tests que vous trouverez jsperf.com/regexp-test-vs-match-m5
ajax333221
@ ajax333221. Merci pour le jsperf, mais je ne suis pas sûr que ce soit un bon. La correspondance d'expression régulière à l'aide d'un groupe de correspondance, ce qui n'est pas nécessaire lors de la recherche d'une valeur booléenne.
gdoron soutient Monica le

Réponses:

440

Utilisation de base

Voyons d'abord ce que fait chaque fonction:

regexObject . test ( String )

Exécute la recherche d'une correspondance entre une expression régulière et une chaîne spécifiée. Renvoie vrai ou faux .

chaîne . match ( RegExp )

Utilisé pour récupérer les correspondances lors de la mise en correspondance d'une chaîne avec une expression régulière. Renvoie un tableau avec les correspondances ou nulls'il n'y en a pas.

Depuis nullévalue à false,

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

Performance

Y a-t-il une différence concernant les performances?

Oui . J'ai trouvé cette courte note sur le site MDN :

Si vous devez savoir si une chaîne correspond à une expression régulière regexp, utilisez regexp.test (string).

La différence est-elle significative?

La réponse est encore OUI ! Ce jsPerf que j'ai mis en place montre que la différence est de ~ 30% - ~ 60% selon le navigateur:

test vs match |  Test de performance

Conclusion

À utiliser .testsi vous souhaitez une vérification booléenne plus rapide. Utilisez .matchpour récupérer toutes les correspondances lors de l'utilisation du gdrapeau global.

gdoron soutient Monica
la source
5
Pas trop surpris car la fonction de chaîne doit retourner les choses puis créer le tableau s'il y a une correspondance. On dirait que je vais continuer à utiliser .test(). :)
22
Mes deux cents: les performances sont surévaluées. L'une ou l'autre option peut effectuer environ 15 000 opérations dans le scintillement d'un moniteur, donc à moins que vous ne fassiez du regex en bloc côté client, la vitesse n'est pas pertinente. Bien sûr, «test» est logiquement la fonction correcte si un résultat booléen est ce que vous recherchez. Merci pour le Q / A BTW.
David Gilbertson
2
Fait intéressant, le test est 41% plus lent que le match pour moi en utilisant le test jsPerf ci-dessus (Chrome 41, OSX).
Benjie
1
@AlexShilman indexOf est plus rapide (mais pas beaucoup) que de tester selon ce stackoverflow.com/questions/183496/… (vous vous attendez à ce qu'il soit plus rapide).
podperson
1
Une chose qui pourrait vous mordre ici (ça a mordu mon équipe récemment): Si vous utilisez le drapeau 'g' sur votre Regex et créez une nouvelle instance (c'est-à-dire via un nouveau RegExp (<regex_str>, 'g')) et que vous réutilisez Par exemple, l'exécution de "test" est avec état, c'est-à-dire qu'elle renverra des résultats différents lorsqu'elle sera exécutée plusieurs fois. Voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… pour plus de détails.
davertron
118

N'oubliez pas de prendre en compte le drapeau global dans votre expression régulière:

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

En effet, Regexp garde la trace du lastIndex lorsqu'une nouvelle correspondance est trouvée.

gtournie
la source
21
J'étais juste en train de frapper la tête en voyant que mon regex.test () enregistrait au hasard "vrai" puis "faux" puis "vrai" ... merci!
adriendenat
7
Je pense que c'est la meilleure réponse. Cela explique qu'ils ne donnent pas le même résultat et que reg.test () a un piège dangereux. Pour moi, cela fait de string.match () le choix évident. La performance n'a jamais été un problème pour moi.
James
2
C'est important! Devenir fou en essayant de comprendre pourquoi tous les autres résultats étaient manquants ... pour référence à toute autre personne qui trouve cela: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dan
2
Si vous êtes aussi confus que moi, consultez stackoverflow.com/q/1520800/3714913 . Il y a aussi String.prototype.search () , qui retourne un index mais n'a pas ce problème pour autant que je sache.
Nateowami
3
Juste curieux, à quoi sert d'avoir un drapeau mondial .test()? n'est pas le point de .test()vérifier si la chaîne a une expression rationnelle correspondante?
buhbang
0

Ce sont mes résultats de référence résultats de référence

test 4267740 ops / sec ± 1,32% (60 passages échantillonnés)

3 649 719 opérations / s ± 2,51% (60 cycles échantillonnés)

correspond à 3 623 125 opérations / s ± 1,85% (62 séries échantillonnées)

index De 6 230 325 ops / sec ± 0,95% (62 passages échantillonnés)

la méthode de test est plus rapide que la méthode de correspondance, mais la méthode la plus rapide est l'indexOf

Ramil Shavaleev
la source
indexOf ne fonctionne pas avec les expressions rationnelles si peu pertinentes.
gdoron soutient Monica