5

I had another question and although it was answered i dont understand WHY the regex is affected the way it is

From w3schools it says

g: Perform a global match (find all matches rather than stopping after the first match)

Ok sure. I understand. Thats why i get an array in this code

var str="The rain in SPAIN stays mainly in the plain";
var patt1=/ain/gi;
document.write(str.match(patt1));

Output:

ain,AIN,ain,ain 

Regex is similar, with /g it will replace more than one instance.

However in match

var re=/hi/gi;
alert(re.test("hi") + " " + re.test("hi"));

The result is "true false".

Now why the $%^& does it do that? The string in both test are exactly the same! In the past i thought global meant it will search across newlines (which is what i wanted to do in this test). The very first thing i quoted was about g being a global match.

Nothing makes any reference about it affecting the NEXT CALL! without /g the code will work correctly (also i dont need to go across newlines). WHY is it affecting the next test? gumbo answer makes mention it affects the lastIndex across calls and what the %^&* i had no idea there is shared state as the other two functions made no use of it while i used the g flag. I only wanted a true and false but if anything shouldnt match return an int containing the amount of matches it found globally? (ie 1 in "hi" but 2 in the string "hihi").

Why the heck is g affecting my next call when doing regex.test?! Also if you can, provide when i'd actually want that 'feature'

Community
  • 1
  • 1
  • w3schools is not to be trusted, see [w3fools](http://w3fools.com) for details. If you get your JS information anywhere, get it from [MDN](https://developer.mozilla.org/). – zzzzBov Mar 26 '12 at 14:00
  • @zzzzBov I tried to find a 'javascript' manual in the past and didnt think of mdn bc i thought it was firefox specific. ok i will check there next time! –  Mar 26 '12 at 14:22
  • @acidzombie24, for the ultimate refence, use the ECMAscript spec, downloadable as a PDF. Yes, it's cumbersome to use as a quick reference, but it's the authoritative guide! MDN is probably your first port-of-call, though, as zzzzBov says. – Doin Jan 14 '14 at 12:20

2 Answers2

9

When you use the global flag in the regex, the lastIndex property is updated. The lastIndex property is the index at which to start the next match.

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp

You can reset the last index before calling again. See

Why RegExp with global flag in Javascript give wrong results?

Community
  • 1
  • 1
Matt Esch
  • 22,661
  • 8
  • 53
  • 51
  • ok but it makes no mention of global having that behavior although it mentions lastIndex (without much of an explanation) and exec. Theres no apparent reason why it has that behavior or what i can use it for. -edit- It doesnt even mention both lastIndex and global together anywhere. Its like that behavior is completely undocumented! –  Mar 26 '12 at 13:52
  • If you read the comments on the linked SO question - "That's what the spec dictates. So, it's a design choice. It's all in section 15.10.6.2 of the ECMAScript 3 specification." – Matt Esch Mar 26 '12 at 13:55
  • It doesnt really talk about design reasons. I guess if your implementing exec (which i never used for the moment) it makes sense. But i am using test here. I... dont expect that behavour especially when match and replace dont seem to have it. +1 bc you did answer the question although i think i think ECMAScript3 specs is nonsense. –  Mar 26 '12 at 14:28
  • 1
    I also feel we have just resigned to the fact that it's in the spec. I would really like to hear the justification, if any was made, because it does seem painful to work with. – Matt Esch Mar 26 '12 at 14:52
0

To me, the main problem seems to be that you are using the 'g' modifier instead of the 'm' modifier, which basically adds '\n' to the set of matched characters by '.'.

The 'g' modifier is used if you want to iterate over given matches, please have a look at http://perldoc.perl.org/perlretut.html#Using-regular-expressions-in-Perl (and search on that page for "Global matching"). Although this is Perl documentation, there is a nice example for a use case.

The Javascript implementation is still flawed as far as I can see, because also

alert(re.test(new String("hi")) + " " + re.test(new String("xhi")));

yields the results you described. But now, the two strings are different Objects and they have different values which should have reset the index of re, but obviously, it didn't.

moritz
  • 25,477
  • 3
  • 41
  • 36