2011-07-18 14 views
10

He estado luchando con esto todo el día, y no puedo entender si estoy haciendo algo mal o si he encontrado un error en el motor JavaScript de Chrome . Parece que las llamadas consecutivas a un objeto RegExp con el indicador global devuelve resultados inconsistentes para la misma cadena de entrada. Estoy probando con la siguiente función:Llamadas consecutivas a la prueba RegExp fallan para el patrón con la opción global

function testRegex(pattern, array) { 
    document.writeln('Pattern = ' + pattern + ', Array = ' + array + '<br/>'); 
    for (var ii = 0; ii < array.length; ii++) { 
     document.writeln(ii + ', '); 
     document.writeln(array[ii] + ', '); 
     document.writeln(pattern.test(array[ii]) + '<br />'); 
    } 
    document.writeln('<br/>'); 
} 

Cuando llamo a la función con /a/g como el patrón y varias matrices de cadenas, consigo los siguientes resultados, muchos de los cuales son incorrectos por lo que yo puedo decir:

// EXPECTED: True 
// ACTUAL: True 
testRegex(/a/g, ['a']); 

// EXPECTED: True, True 
// ACTUAL: True, False 
testRegex(/a/g, ['a', 'a']); 

// EXPECTED: True, True, True 
// ACTUAL: True, False, True 
testRegex(/a/g, ['a', 'a', 'a']); 

// EXPECTED: True, False, True 
// ACTUAL: True, False, True 
testRegex(/a/g, ['a', 'b', 'a']); 

// EXPECTED: True, True, True, True 
// ACTUAL: True, False, True, False 
testRegex(/a/g, ['a', 'a', 'a', 'a']); 

// EXPECTED: True, False, False, True 
// ACTUAL: True, False, False, True 
testRegex(/a/g, ['a', 'b', 'b', 'a']); 

Cuando llamo a la misma función con los mismos arreglos de cuerdas, sino que pasan /a/ como el patrón, los resultados reales todos coinciden con los resultados esperados.

// EXPECTED: True 
// ACTUAL: True 
testRegex(/a/, ['a']); 

// EXPECTED: True, True 
// ACTUAL: True, True 
testRegex(/a/, ['a', 'a']); 

// EXPECTED: True, True, True 
// ACTUAL: True, True, True 
testRegex(/a/, ['a', 'a', 'a']); 

// EXPECTED: True, False, True 
// ACTUAL: True, False, True 
testRegex(/a/, ['a', 'b', 'a']); 

// EXPECTED: True, True, True, True 
// ACTUAL: True, True, True, True 
testRegex(/a/, ['a', 'a', 'a', 'a']); 

// EXPECTED: True, False, False, True 
// ACTUAL: True, False, False, True 
testRegex(/a/, ['a', 'b', 'b', 'a']); 

He creado un ejemplo de trabajo del código anterior: http://jsfiddle.net/FishBasketGordo/gBWsN/

Me estoy perdiendo algo? ¿No deberían los resultados ser los mismos para las matrices de cadenas dadas, sin importar si el patrón es global o no? Tenga en cuenta, en primer lugar he estado trabajando en Chrome, pero he observado resultados incorrectos similares en Firefox 4 e Internet Explorer 8.

Respuesta

15

Si cambia de bucle de prueba de la siguiente manera:

for (var ii = 0; ii < array.length; ii++) { 
    document.writeln(ii + ', '); 
    document.writeln(array[ii] + ', '); 
    document.writeln(pattern.test(array[ii]) + '<br />'); 
    pattern.lastIndex = 0; 
} 

A continuación, el código se trabajo. El problema es que la bandera "g" hace que el objeto RegExp se atasque. El valor "lastIndex" se establece en 1 después de la primera iteración de ese ciclo, debido a la "g". Si no lo configura de nuevo para restablecer la búsqueda, se supone que en la segunda llamada le pedirá que continúe desde el desplazamiento 1.

Usando el indicador "g" en una expresión regular fuera del contexto de una llamada ".replace()" tiene implicaciones semánticas impares de todos modos.

+0

Mi objetivo partiendo de esta mañana era utilizar finalmente la expresión regular en 'replace', por lo que yo estaba usando la opción global para empezar, pero como mi RegExp, me quedé atrapado en un paso intermedio . – FishBasketGordo

6

No es un error, sino una característica. Los resultados que obtiene no son "incorrectos", solo inesperados.

10.3.2. Propiedades de instancia de RegExp

Cada objeto RegExp tiene cinco propiedades. La propiedad de origen es una cadena de solo lectura que contiene el texto de la expresión regular. La propiedad global es un valor booleano de solo lectura que especifica si la expresión regular tiene el indicador g. La propiedad ignoreCase es un valor booleano de solo lectura que especifica si la expresión regular tiene el indicador i. La propiedad multilínea es un valor booleano de solo lectura que especifica si la expresión regular tiene el indicador m. La propiedad final es lastIndex, un entero de lectura-escritura. Para los patrones con el indicador g, esta propiedad almacena la posición en la cadena en la cual comenzará la siguiente búsqueda. Es utilizado por los métodos exec() y test(), como se describe en la sección anterior.

Source

Cuestiones relacionadas