Regular expressions with the global flag turned on can be a source of tricky bugs for uninformed users, and should therefore be used with caution.
Such regular expressions are stateful, that is, they maintain an internal state through the lastIndex
property, which is updated and used
as starting point on every call to RegExp.prototype.test()
and RegExp.prototype.exec()
, even when testing a different
string. The lastIndex
property is eventually reset when these functions return false
and null
respectively.
This rule raises an issue when:
- a regular expression is tested against different inputs with
RegExp.prototype.test()
or RegExp.prototype.exec()
- a regular expression is defined within a loop condition while used with
RegExp.prototype.exec()
- a regular expression turns on both global
g
and sticky y
flags
Noncompliant Code Example
const datePattern = /\d{4}-\d{2}-\d{2}/g;
datePattern.test('2020-08-06');
datePattern.test('2019-10-10'); // Noncompliant: the regex will return "false" despite the date being well-formed
const str = 'foodie fooled football';
while ((result = /foo*/g.exec(str)) !== null) { // Noncompliant: a regex is defined at each iteration causing an infinite loop
/* ... */
}
const stickyPattern = /abc/gy; // Noncompliant: a regex defined as both sticky and global ignores the global flag
stickyPattern.test(/* ... */);
Compliant Solution
const datePattern = /\d{4}-\d{2}-\d{2}/;
datePattern.test('2020-08-06');
datePattern.test('2019-10-10'); // Compliant
const reg = /foo*/g;
const str = 'foodie fooled football';
while ((result = reg.exec(str)) !== null) { // Compliant
/* ... */
}
const stickyPattern = /abc/y; // Compliant
stickyPattern.test(/* ... */);