Skip to content

Document that String.prototype.replace() resets lastIndex for global regexes - #44941

Closed
btea wants to merge 1 commit into
mdn:mainfrom
btea:string-replace-reset-lastindex
Closed

Document that String.prototype.replace() resets lastIndex for global regexes#44941
btea wants to merge 1 commit into
mdn:mainfrom
btea:string-replace-reset-lastindex

Conversation

@btea

@btea btea commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Description

Explain that when the pattern is a regex with the g flag, replace() sets the regex's lastIndex to 0 before matching and leaves it at 0 after the call, so there is no need to manually reset lastIndex after using the same regex with methods like test(). Also note that non-global regexes do not get their lastIndex reset.

Per ECMA-262:

Motivation

Additional details

Related issues and pull requests

…regexes

Explain that when the pattern is a regex with the g flag, replace() sets the regex's lastIndex to 0 before matching and leaves it at 0 after the call, so there is no need to manually reset lastIndex after using the same regex with methods like test(). Also note that non-global regexes do not get their lastIndex reset.

Per ECMA-262:
- https://tc39.es/ecma262/multipage/text-processing.html#sec-string.prototype.replace
- https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
@btea
btea requested a review from a team as a code owner July 28, 2026 01:58
@btea
btea requested review from Josh-Cena and removed request for a team July 28, 2026 01:58
@github-actions github-actions Bot added Content:JS JavaScript docs size/s [PR only] 6-50 LoC changed labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@Josh-Cena Josh-Cena left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, but as the paragraph directly preceding your addition says, all behaviors related to the regex itself is documented in the regex reference instead. The String method merely calls that method so this behavior doesn't pertain to it at all. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/Symbol.replace offers a detailed explanation about how lastIndex is changed.

@Josh-Cena Josh-Cena closed this Jul 28, 2026
@btea

btea commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for pointing that out — I hadn't noticed the RegExp.prototype[Symbol.replace]() page, which already documents this behavior.

@btea

btea commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

One follow-up after re-reading the spec and the current page: the RegExp.prototype[Symbol.replace]() page explains that exec() is called repeatedly until it returns null, and that the final failing exec() resets lastIndex to 0. However, it does not explicitly mention that the algorithm also resets lastIndex to 0 before matching starts.

Per ECMA-262 RegExp.prototype [ @@replace ], step 6:

If global is true, then
a. Perform ? Set(rx, "lastIndex", +0𝔽, true).

So for global regexes, matching always starts from the beginning of the string regardless of the regex's previous lastIndex (e.g. left behind by a prior test() call). The observable "left at 0 after the call" behavior comes from the failing exec() in the loop (per RegExpBuiltinExec, which sets lastIndex to 0 on failure for global/sticky regexes) — but the "starts from the beginning" guarantee comes from this entry step, which the page currently does not state.

Do you think it is worth adding one sentence to that page, e.g. "If the regex is global, lastIndex is first set to 0, so matching always starts from the beginning of the string"? Happy to open a new PR for that if you agree.

@Josh-Cena

Copy link
Copy Markdown
Member

Yeah, I think that might be worth mentioning. Happy to take another PR!

@btea
btea deleted the string-replace-reset-lastindex branch July 29, 2026 14:00
@btea

btea commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Opened #44957 to add the note about lastIndex being reset to 0 before matching on the RegExp.prototype[Symbol.replace]() page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Content:JS JavaScript docs size/s [PR only] 6-50 LoC changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants