23 Stimmen

Javascript Regex Literal mit /g mehrfach verwendet

Ich habe ein seltsames Problem bei der Arbeit mit der Javascript-Funktion Regexp.exec. Wenn ich die Funktion mehrmals für neue (ich schätze ...) Regexp-Objekte aufrufe, funktioniert sie nur jedes zweite Mal. Ich verstehe nicht, warum überhaupt!

Hier ist ein kleines Beispiel für eine Schleife, die aber dasselbe tut, wenn sie einmal in einer Funktion verwendet und mehrmals aufgerufen wird.

for (var i = 0; i < 5; ++i) {
  console.log(i, (/(b)/g).exec('abc'));
}

> 0 ["b", "b"]
> 1 null
> 2 ["b", "b"]
> 3 null
> 4 ["b", "b"]

Wenn Sie das /g entfernen, kehrt es zum normalen Zustand zurück.

for (var i = 0; i < 5; ++i) {
  console.log(i, (/(b)/).exec('abc'));
}             /* no g ^ */

> 0 ["b", "b"]
> 1 ["b", "b"]
> 2 ["b", "b"]
> 3 ["b", "b"]
> 4 ["b", "b"]

Ich vermute, dass es eine Optimierung gibt, die das Regexp-Objekt speichert, aber es scheint seltsam.

Dieses Verhalten ist bei Chrome 4 und Firefox 3.6 dasselbe, funktioniert aber im IE8 wie erwartet. Ich glaube, das ist beabsichtigt, aber ich kann die Logik darin nicht finden, vielleicht können Sie mir helfen!

Danke

23voto

Pointy Punkte 387467

Wenn Sie denselben regulären Ausdruck ohnehin wiederverwenden wollen, nehmen Sie ihn aus der Schleife heraus und setzen Sie ihn explizit zurück:

var pattern = /(b)/g;
for (var i = 0; i < 5; ++i) {
  pattern.lastIndex = 0;
  console.log(i + ' ' + pattern.exec("abc"));
}

19voto

SilentGhost Punkte 285785

/g ist nicht für den einfachen Abgleich gedacht :

/g ermöglicht einen "globalen" Abgleich. Bei Verwendung der Option replace() Methode, geben Sie diesen Modifikator an, um alle Übereinstimmungen zu ersetzen, nicht nur die erste.

Ich könnte mir vorstellen, dass intern Javascript den Abgleich nach der Erfassung hält, so dass es in der Lage wäre, den Abgleich fortzusetzen und daher null zurückgegeben wird, da b nur einmal im Thema vorkommen. Vergleichen Sie:

for (var i = 0; i < 5; ++i) {
  console.log(i +'    ' + (/(b+)/g).exec("abbcb"));
}

zurück:

0 bb,bb
1 b,b
2 null
3 bb,bb
4 b,b

2voto

Vjeux Punkte 5726

Danke :)

Ich habe einen interessanten Nebeneffekt entdeckt: Es ist möglich, eine statische Variable (im Sinne von C, global aber nur von der Funktion aus sichtbar) ohne Closure zu erstellen!

   function test () {
     var static = /a/g;
     if ('count' in static) {
       static.count++;
     } else {
       static.count = 1;
     }
     console.log(static.count);
   }

   for (var i = 0; i < 5; ++i) { test(); }
   1
   2
   3
   4
   5

(Ich mache eine neue Antwort, weil wir keinen Code in einen Kommentar einfügen können)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X