Consider:
var reg = new RegExp("^19[-\\d]*","g");
reg.test('1973-02-01') // true
reg.test('1973-01-01') // false
Why does the third line return false
? If I remove the "g" flag, then it returns true
.
In JavaScript, regular expression objects have state. This matters when the g
flag ("global") is applied to them, and sometimes applies in odd ways. This state is the index where the match last occurred, which is the regex's .lastIndex
property. When you call exec
or test
on the same regex object again, it picks up from where it left off.
What's happening in your example is for the second call, it's picking up where it left off the last time, and so it's looking starting after the 10th character in the string — and doesn't find a match there, because there's no text there at all (and even if there were, the ^
assertion wouldn't match).
We can see what's happening if we look at the lastIndex
property:
var reg = new RegExp("^19[-\\d]*","g");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Without the g
flag, the regex object doesn't keep any state and starts from the beginning of the string each time:
var reg = new RegExp("^19[-\\d]*");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Side note: In general, it's best to write regular expressions in JvaScript using regex literals rather than using the RegExp
constructor and strings. In your case, that would be
var reg = /^19[-\d]*/g;
// or without the g flag:
var reg = /^19[-\d]*/;
Side note 2: It doesn't make much sense to define a regular expression with a ^
or $
anchor and the g
flag unless you're also using the m
(multiline) flag to change what those anchors mean. without m
, they mean "beginning (^
) or end ($
) of input." With the m
flag, they mean "beginning (^
) or end ($
) of line."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With