开发者

Javascript Regex literal with /g used multiple times

I have a weird issue working with the Javascript Regexp.exec function. When calling multiple time the function on new (I guess ...) regexp objects, it works one time every two. I don't get why at all!

Here is a little loop example but it does the same thing when used one time in a function and called multiple times.

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

When removing the /g, it gets back to normal.

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

I开发者_开发技巧 guess that there is an optimization, saving the regexp object, but it seems strange.

This behaviour is the same on Chrome 4 and Firefox 3.6, however it works as (I) expected in IE8. I believe that is intended but I can't find the logic in there, maybe you will be able to help me!

Thanks


If you're going to reuse the same regular expression anyway, take it out of the loop and explicitly reset it:

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


/g is not intended to work for simple matching:

/g enables "global" matching. When using the replace() method, specify this modifier to replace all matches, rather than only the first one.

I'd imagine internally javascript holds the matching after the capture, so it would be able to resume matching and therefore null is returned since b occur only once in the subject. Compare:

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

returns:

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


Thanks :)

I found an interesting side effet, it's possible make a static variable (in sense of C, global but only visible from the function) without closure!

   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

(I'm making a new answer because we can't put code inside a comment)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜