Found useless backreferences in regular expressionsJS-0039
In JavaScript regular expressions, it's syntactically valid to define a backreference to a group that belongs to another alternative part of the pattern, a backreference to a group that appears after the backreference, a backreference to a group that contains that backreference, or a backreference to a group that is inside a negative lookaround. However, by the specification, in any of these cases the backreference always ends up matching only zero-length (the empty string), regardless of the context in which the backreference and the group appear. Backreferences that always successfully match zero-length and cannot match anything else are useless. They are basically ignored and can be removed without changing the behavior of the regular expression.
const regex = /^(?:(a)|\1b)$/;
regex.test("a"); // true
regex.test("b"); // true!
regex.test("ab"); // false
const equivalentRegex = /^(?:(a)|b)$/;
equivalentRegex.test("a"); // true
equivalentRegex.test("b"); // true
equivalentRegex.test("ab"); // false
A useless backreference is a possible error in the code. It usually indicates that the regular expression does not work as intended.
Bad Practice
/^(?:(a)|\1b)$/; // reference to (a) into another alternative
/^(?:(a)|b(?:c|\1))$/; // reference to (a) into another alternative
/^(?:a|b(?:(c)|\1))$/; // reference to (c) into another alternative
/\1(a)/; // forward reference to (a)
RegExp('(a)\2(b)'); // forward reference to (b)
/(?:a)(b)\2(c)/; // forward reference to (c)
/\k<foo>(?<foo>a)/; // forward reference to (?<foo>a)
/(?<=(a)\1)b/; // backward reference to (a) from within the same lookbehind
/(?<!(a)\1)b/; // backward reference to (a) from within the same lookbehind
new RegExp('(\1)'); // nested reference to (\1)
/^((a)\1)$/; // nested reference to ((a)\1)
/a(?<foo>(.)b\1)/; // nested reference to (?<foo>(.)b\1)
/a(?!(b)).\1/; // reference to (b) into a negative lookahead
/(?<!(a))b\1/; // reference to (a) into a negative lookbehind
Recommended
/^(?:(a)|(b)\2)$/; // reference to (b)
/(a)\1/; // reference to (a)
RegExp('(a)\1(b)'); // reference to (a)
/(a)(b)\2(c)/; // reference to (b)
/(?<foo>a)\k<foo>/; // reference to (?<foo>a)
/(?<=\1(a))b/; // reference to (a), correctly before the group as they're in the same lookbehind
/(?<=(a))b\1/; // reference to (a), correctly after the group as the backreference isn't in the lookbehind
new RegExp('(.)\1'); // reference to (.)
/^(?:(a)\1)$/; // reference to (a)
/^((a)\2)$/; // reference to (a)
/a(?<foo>(.)b\2)/; // reference to (.)
/a(?!(b|c)\1)./; // reference to (b|c), correct as it's from within the same negative lookahead
/(?<!\1(a))b/; // reference to (a), correct as it's from within the same negative lookbehind