72 lines
3.5 KiB
Plaintext
72 lines
3.5 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Regular expressions in JavaScript can have a global flag (``++/g++``) that enables global searching and matching. While this flag can be useful in certain scenarios, it should be used with caution. When a regular expression has the global flag enabled, it remembers the position of the last match and continues searching for subsequent matches from that position. This behavior can lead to unexpected results if you're not careful and be a source of bugs that are tricky to debug.
|
|
|
|
The global flag introduces shared state within the regular expression object. This means that if you use the same regular expression object across multiple operations or functions, it maintains its internal state, such as the last match position.
|
|
|
|
[source,javascript,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
const regex = /\d{4}-\d{2}-\d{2}/g;
|
|
regex.test('2020-08-06');
|
|
regex.test('2019-10-10'); // Noncompliant: the regex will return "false" despite the date being well-formed
|
|
----
|
|
|
|
You should not use the global flag if you intend to use the same regular expression across multiple operations.
|
|
|
|
[source,javascript,diff-id=1,diff-type=compliant]
|
|
----
|
|
const regex = /\d{4}-\d{2}-\d{2}/;
|
|
regex.test('2020-08-06');
|
|
regex.test('2019-10-10');
|
|
----
|
|
|
|
Incorrect usage of global regular expressions can result in infinite loops. For example, if you use a different instance of the same regular expression in a `while`, it can continuously match the same substring, causing an infinite loop.
|
|
|
|
[source,javascript,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
const input = 'foodie fooled football';
|
|
while ((result = /foo*/g.exec(input)) !== null) { // Noncompliant: a regex is defined at each iteration causing an infinite loop
|
|
/* ... */
|
|
}
|
|
----
|
|
|
|
To avoid an infinite loop, you should create the regular expression with the global flag only once, assign it to a variable, and use the same variable in the loop.
|
|
|
|
[source,javascript,diff-id=2,diff-type=compliant]
|
|
----
|
|
const regex = /foo*/g;
|
|
const input = 'foodie fooled football';
|
|
while ((result = regex.exec(input)) !== null) {
|
|
/* ... */
|
|
}
|
|
----
|
|
|
|
Mixing the global flag (``++g++``) and the sticky flag (``++y++``) can have different effects on how regular expressions are matched and the behavior of certain methods. The ``++test()++`` method ignores the global flag and behaves as if only the sticky flag is set.
|
|
|
|
[source,javascript,diff-id=3,diff-type=noncompliant]
|
|
----
|
|
const regex = /abc/gy; // Noncompliant: a regex enabling both sticky and global flags ignores the global flag
|
|
regex.test(/* ... */);
|
|
----
|
|
|
|
Therefore, sou should remove the redundant global flag from the regular expression and only enable the sticky flag.
|
|
|
|
[source,javascript,diff-id=3,diff-type=compliant]
|
|
----
|
|
const regex = /abc/y;
|
|
regex.test(/* ... */);
|
|
----
|
|
|
|
Overall, 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
|
|
|
|
== Resources
|
|
=== Documentation
|
|
|
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags[Regular expression flags]
|
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec[``++RegExp.prototype.exec()++``]
|
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test[``++RegExp.prototype.test()++``]
|