2009-03-03 25 views
8

Escribí una prueba Javascript RegExp para detectar el formato de cadena de fecha, agregué por error una bandera "g" redundante y encontré algo interesante.Prueba interesante de Javascript RegExp

var s = "2009/03/10"; 
var regex=/^\d{4}[/]\d{2}[/]\d{2}$/g; 
alert(regex.test(s)); 
alert(regex.test(s)); 
alert(regex.test(s)); 
alert(regex.test(s)); 

tengo un 'verdadero' seguido de un 'falso', y luego otro 'verdadero', y luego otro 'falso'.

Si uso un ciclo para ejecutarlo, encontré algo más interesante, obtuve cuatro "verdaderos" en IE y Safari, y verdadero, falso, verdadero, falso en FF, Chrome.

for (var i=0; i<4; i++) 
{ 
    var s = "2009/03/10"; 
    var regex=/^\d{4}[/]\d{2}[/]\d{2}$/g; 
    alert(regex.test(s)); 
} 

¿Alguien tiene idea de explicar por qué la expresión regular Javascript se comporta de esa manera y lo que los navegadores causa devolver resultados diferentes? (relacionado con la declaración de variables y el alcance de la vida?)

Respuesta

19

Cuando utiliza un indicador global en un JS RegExp, los métodos de "prueba" y "ejecutivo" se detienen cada uno en el primer partido pero mantienen un puntero al lugar donde dejaron de buscar en el cuerda. Ese puntero puede inspeccionarse en la propiedad lastIndex. Cuando llamas de nuevo a "prueba" o "ejecutivo", comienza a buscar una coincidencia que comienza en el lastIndex.

Por lo tanto, cuando pruebe un RegExp en una cadena que coincida con toda la cadena, lastIndex se configurará al final de la cadena. La próxima vez que lo pruebe, comienza al final de la cadena, devuelve false y establece lastIndex en cero.

El MDC tiene un decent explanation de este comportamiento.

+0

Muchas gracias, explicación del MDC es muy clara. – Darkthread

+0

+1 gracias por la ayuda, estableciendo reg.lastIndex = 0 antes de cada prueba resolvió mi problema. – bendewey

+0

Parece que puede establecer lastIndex = 0 antes de cada prueba si esto está causando problemas dentro de un bucle, por ejemplo. – k0nG

0

Para evitar este comportamiento extraño, no use la bandera global (g).

Este código es la Salida: 'True', 'True', 'True', 'True'

var s = "2009/03/10"; 
var regex=/^\d{4}[/]\d{2}[/]\d{2}$/i; 
alert(regex.test(s)); 
alert(regex.test(s)); 
alert(regex.test(s)); 
alert(regex.test(s)); 

El mundial (g) establecer plano del RegExp.lastIndex propiedad. Entonces, cada prueba() comenzará donde se detuvo la última.

Para más información ver la documentación sobre RegExp.lastIndex