Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does JavaScript's RegExp maintain state between calls? [duplicate]

Today I came across a very strange JavaScript regular expression issue. When using the global modifier (//g), RegExp.test() yields different values in subsequent calls. Can anyone explain why?

var s = "youtube.com/watch?v=XyeebVA3DNk";

var re1 = /^youtube\.com\/watch[a-zA-Z0-9_\-\?\&\=\/]+/g;

console.log(re1.test(s)); // true
console.log(re1.test(s)); // false
console.log(re1.test(s)); // true
console.log(re1.test(s)); // false
console.log(re1.test(s)); // true
console.log(re1.test(s)); // false
console.log(re1.test(s)); // true

var re2 = /^youtube\.com\/watch[a-zA-Z0-9_\-\?\&\=\/]+/;

console.log(re2.test(s)); // true
console.log(re2.test(s)); // true
console.log(re2.test(s)); // true
console.log(re2.test(s)); // true
console.log(re2.test(s)); // true
console.log(re2.test(s)); // true

I am able to reproduce this in Chrome 8 and FireFox 3.6.

like image 330
J.P. Avatar asked Jan 14 '11 06:01

J.P.


2 Answers

It's only when you use the g flag. I agree it's not the best design, but the point is to let you loop over the matches, e.g. with re1.exec.

var s = "fo1,fo2,fo3,"; 
var re1 = /fo\d,/g;
var match;
while(match = re1.exec(s)) 
{ 
  alert(match); 
}
like image 55
Matthew Flaschen Avatar answered Sep 18 '22 04:09

Matthew Flaschen


"If your regular expression uses the "g" flag, you can use the exec method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of s specified by the regular expression's lastIndex property (test will also advance the lastIndex property)."

"As with exec (or in combination with it), test called multiple times on the same global regular expression instance will advance past the previous match."

var s = "youtube.com/watch?v=XyeebVA3DNk";

var re1 = /^youtube\.com\/watch[a-zA-Z0-9_\-\?\&\=\/]+/g;

console.log(re1.test(s)); // true

var re1 = /^youtube\.com\/watch[a-zA-Z0-9_\-\?\&\=\/]+/g;

console.log(re1.test(s)); // true
like image 44
G.G. Avatar answered Sep 20 '22 04:09

G.G.