-1

I just stumbled over this very strange behavior. I have a regex that extracts Youtube video IDs from embedded iframes. The regex looks like this:

var regex = /(?:youtu\.be|youtube\.com|ytimg\.com|youtube-nocookie\.com).*(?:\/|\?v=|\&v=|\?video_id=|\&video_id=)([\w\-_]{11})[^\w\-_]?/ig;

I now have an embedded Youtube iframe that looks like this:

<iframe id="ytplayer" type="text/html" width="300" height="200"
  src="//www.youtube.com/embed/M7lc1UVf-VE?autoplay=0&origin=//example.com"
  frameborder="0"/>

As you can see, that regex should match against the src attribute of this element. However, if I do the following code it will return false:

regex.test( $('#ytplayer').attr('src') );

You will say "Well, your regex is obviously wrong, check it again". But then have a look at this:

regex.test( $('#ytplayer').attr('src').toString() );

This will return true even though it is the exact same code, only with an added toString(). And yes, .attr('src') already returns a string! Why is this? I can reproduce this in Chrome and Firefox so it's most likely not a bug in a JS implementation.

(You can find a JsFiddle to try it out here)

David Thomas
  • 249,100
  • 51
  • 377
  • 410
Martin Thurau
  • 7,564
  • 7
  • 43
  • 80

1 Answers1

3

Since you are using the regex for testing do not use g flag

var regex = /(?:youtu\.be|youtube\.com|ytimg\.com|youtube-nocookie\.com).*(?:\/|\?v=|\&v=|\?video_id=|\&video_id=)([\w\-_]{11})[^\w\-_]?/i;

When you use the g flag the regex processor will remember the position of the last search and in the next search it will continue from there. if there was no match in the second search again the index will get resetted to 0;

Demo: Fiddle

If you want further clarity look at this demo where the same search is repeated one after another where first one matches and second one fails

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • Yes, this is due to `g` flag. `var regex = /(?:content)/ig; [ regex.test( $('#content').attr('id') ), regex.test( $('#content').attr('id') ), regex.test( $('#content').attr('id') ), regex.test( $('#content').attr('id') ), regex.test( $('#content').attr('id') ) ] [true, false, true, false, true]` – kirilloid May 15 '13 at 10:28
  • "Well, your regex is obviously wrong, check it again". I'm feeling rather stupid right now :( – Martin Thurau May 15 '13 at 10:35
  • @MartinThurau I had done the same mistake and asked a similar question in SO before http://stackoverflow.com/questions/15610251/why-pattern-testname-opposite-results-on-consecutive-calls – Arun P Johny May 15 '13 at 10:36