RegExp.prototype.sticky
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
Thesticky accessor property ofRegExp instances returns whether or not they flag is used with this regular expression.
In this article
Try it
const str = "table football";const regex = /foo/y;regex.lastIndex = 6;console.log(regex.sticky);// Expected output: trueconsole.log(regex.test(str));// Expected output: trueconsole.log(regex.test(str));// Expected output: falseDescription
RegExp.prototype.sticky has the valuetrue if they flag was used; otherwise,false. They flag indicates that the regex attempts to match the target string only from the index indicated by thelastIndex property (and unlike a global regex, does not attempt to match from any later indexes).
The set accessor ofsticky isundefined. You cannot change this property directly.
For both sticky regexes andglobal regexes:
- They start matching at
lastIndex. - When the match succeeds,
lastIndexis advanced to the end of the match. - When
lastIndexis out of bounds of the currently matched string,lastIndexis reset to 0.
However, for theexec() method, the behavior when matching fails is different:
- When the
exec()method is called on a sticky regex, if the regex fails to match atlastIndex, the regex immediately returnsnulland resetslastIndexto 0. - When the
exec()method is called on a global regex, if the regex fails to match atlastIndex, it tries to match from the next character, and so on until a match is found or the end of the string is reached.
For theexec() method, a regex that's both sticky and global behaves the same as a sticky and non-global regex. Becausetest() is a simple wrapper aroundexec(),test() would ignore the global flag and perform sticky matches as well. However, due to many other methods special-casing the behavior of global regexes, the global flag is, in general, orthogonal to the sticky flag.
String.prototype.matchAll()(which callsRegExp.prototype[Symbol.matchAll]()):y,gandgyare all different.- For
yregexes:matchAll()throws;[Symbol.matchAll]()yields theexec()result exactly once, without updating the regex'slastIndex. - For
gorgyregexes: returns an iterator that yields a sequence ofexec()results.
- For
String.prototype.match()(which callsRegExp.prototype[Symbol.match]()):y,gandgyare all different.- For
yregexes: returns theexec()result and updates the regex'slastIndex. - For
gorgyregexes: returns an array of allexec()results.
- For
String.prototype.search()(which callsRegExp.prototype[Symbol.search]()): thegflag is always irrelevant.- For
yorgyregexes: always returns0(if the very beginning of the string matches) or-1(if the beginning doesn't match), without updating the regex'slastIndexwhen it exits. - For
gregexes: returns the index of the first match in the string, or-1if no match is found.
- For
String.prototype.split()(which callsRegExp.prototype[Symbol.split]()):y,g, andgyall have the same behavior.String.prototype.replace()(which callsRegExp.prototype[Symbol.replace]()):y,gandgyare all different.- For
yregexes: replaces once at the currentlastIndexand updateslastIndex. - For
gandgyregexes: replaces all occurrences matched byexec().
- For
String.prototype.replaceAll()(which callsRegExp.prototype[Symbol.replace]()):y,gandgyare all different.- For
yregexes:replaceAll()throws. - For
gandgyregexes: replaces all occurrences matched byexec().
- For
Examples
>Using a regular expression with the sticky flag
const str = "#foo#";const regex = /foo/y;regex.lastIndex = 1;regex.test(str); // trueregex.lastIndex = 5;regex.test(str); // false (lastIndex is taken into account with sticky flag)regex.lastIndex; // 0 (reset after match failure)Anchored sticky flag
For several versions, Firefox's SpiderMonkey engine hada bug with regard to the^ assertion and the sticky flag which allowed expressions starting with the^ assertion and using the sticky flag to match when they shouldn't. The bug was introduced some time after Firefox 3.6 (which had the sticky flag but not the bug) and fixed in 2015. Perhaps because of the bug, the specificationspecifically calls out the fact that:
Even when the
yflag is used with a pattern,^always matches only at the beginning ofInput, or (ifrer.[[Multiline]] istrue) at the beginning of a line.
Examples of correct behavior:
const regex1 = /^foo/y;regex1.lastIndex = 2;regex1.test("..foo"); // false - index 2 is not the beginning of the stringconst regex2 = /^foo/my;regex2.lastIndex = 2;regex2.test("..foo"); // false - index 2 is not the beginning of the string or lineregex2.lastIndex = 2;regex2.test(".\nfoo"); // true - index 2 is the beginning of a lineSpecifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-get-regexp.prototype.sticky> |