2009-11-19 8 views

Répondre

12

Conformément à la spécification ES3, ils sont légèrement différents en ce que la syntaxe littérale (/regex/) va créer un objet unique RegExp sur l'analyse initiale:

Une expression régulière littérale est un élément d'entrée qui est converti en un objet RegExp (section 15.10) lorsqu'il est analysé . L'objet est créé avant que l'évaluation du programme contenant ne commence. L'évaluation du littéral produit une référence à cet objet; il ne crée pas un nouvel objet .

L'erreur dans cette spécification a été reconnue dans ES4:

Dans ES3 une expression régulière littérale comme/ab/mg désigne un seul objet unique RegExp qui a créé la première fois le littéral est rencontré pendant l'évaluation. Dans ES4, un nouvel objet RegExp est créé chaque fois le littéral est rencontré pendant l'évaluation .

Les implémentations varient selon les navigateurs. Safari et IE traitent les littéraux selon ES4, mais Firefox et Chrome semblent les traiter selon ES3.

Essayez le code suivant dans différents navigateurs et vous verrez ce que je veux dire:

function f() { 
    return /abc/g.test('abc'); 
} 

alert(f()); // Alerts true 
alert(f()); // Alerts false in FF/Chrome 

Par rapport à:

function f() { 
    return RegExp('abc', 'g').test('abc'); 
} 

alert(f()); // Alerts true 
alert(f()); // Alerts true 

Remarque, false est alertée parce que la fonction utilise toujours l'expression rationnelle à partir de l'appel précédent de cette fonction, le lastIndex a été mis à jour, ce qui signifie qu'il ne correspondra plus à la chaîne "abc".


Astuce: l'opérateur new n'est pas nécessaire pour RegExp à instancier. RegExp() par lui-même fonctionne de la même ...


Plus d'informations sur la question ES3/4: Regex/lastIndex - Unexpected behaviour

+0

Ça m'intéresse, mec. C'est intéressant. –

+0

Ainsi, vous pouvez argumenter que l'utilisation du formulaire en ligne sera légèrement plus efficace (au moins en ES3). Alors que le formulaire RegExp produirait un résultat d'implémentation croisée plus cohérent. Impressionnant! –

+0

+1 bonne trouvaille/réponse – cletus

2

Selon J-P's answerest une légère différence, ce qui peut parfois être important. L'intention était que:

var re = /\d+/; 

être le même que:

var re = new RegExp("\\d+"); 

mais, curieusement, dans Firefox/Chrome est pas tout à fait même (comme l'a démontré par son exemple avec expressions avec état utilisées plusieurs fois). Donc, utilisez l'objet RegExp serait mon conseil. Et une excellente trouvaille par J-P.

Cela étant dit, la principale circonstance où vous deviez utiliser RegExp sur la syntaxe littérale de toute façon était de créer dynamiquement des expressions, par exemple: méthode

var s = "[asdf]+"; 
var re = new RegExp(":" + s + ":", "g"); 
+2

Il y a doit y avoir plus de différence définie. Ma motivation pour poser cette question était parce que JSLint semble ne pas aimer le format en ligne. Malheureusement, je ne pouvais pas trouver une raison compréhensible pour expliquer pourquoi. –

+2

JSLint n'aime pas beaucoup de choses qui sont pratiquement identiques. Rappelez-vous que JSLint est un vérificateur * style *, pas seulement un vérificateur de syntaxe. Il est très probablement mal vu par M. Crockford parce qu'il pourrait être difficile à comprendre ou quelque chose de similaire. – nickf