Javascript Regex литерал с / г используется несколько раз - PullRequest
17 голосов
/ 26 января 2010

У меня странная проблема с работой функции Javascript Regexp.exec. При многократном вызове функции для новых (я думаю ...) объектов регулярных выражений она работает один раз каждые два. Я вообще не понимаю, почему!

Вот небольшой пример цикла, но он делает то же самое, когда используется один раз в функции и вызывается несколько раз.

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"]

При удалении / g возвращается в нормальное состояние.

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"]

Я предполагаю, что есть оптимизация, сохраняющая объект регулярного выражения, но это кажется странным.

Это поведение одинаково в Chrome 4 и Firefox 3.6, однако оно работает так, как (I) ожидалось в IE8. Я верю, что это задумано, но я не могу найти там логику, может быть, вы сможете мне помочь!

Спасибо

Ответы [ 3 ]

18 голосов
/ 26 января 2010

Если вы все равно собираетесь использовать одно и то же регулярное выражение, выньте его из цикла и явно сбросьте его:

var pattern = /(b)/g;
for (var i = 0; i < 5; ++i) {
  pattern.lastIndex = 0;
  console.log(i + ' ' + pattern.exec("abc"));
}
16 голосов
/ 26 января 2010

/g не предназначен для простого сопоставления :

/g включает «глобальное» сопоставление. При использовании метода replace() укажите этот модификатор, чтобы заменить все совпадения, а не только первый.

Я бы предположил, что внутренне javascript содержит совпадения после захвата, поэтому он сможет возобновить сопоставление, и поэтому возвращается null, поскольку b встречается только один раз в теме. Сравните:

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

возвращается:

0 bb,bb
1 b,b
2 null
3 bb,bb
4 b,b
2 голосов
/ 26 января 2010

Спасибо:)

Я нашел интересный побочный эффект, можно сделать статическую переменную (в смысле C, глобальной, но видимой только из функции) без замыкания!

   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

(я делаю новый ответ, потому что мы не можем поместить код в комментарий)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...