4

I notice you can actually get passed your named capture groups in the replace callback:

'Yoda said "fear leads to anger."'.replace(
    /(?<pre>\b\w+\b)(?<betwixt> leads to )(?<post>\b\w+\b)/,
    (...args) => {
        let [{pre, betwixt, post}] = args.slice(-1);
        let ani = {fear:'anger',anger:'hate',hate:'suffering'};
        return `${ani[pre]}${betwixt}${ani[post]}`;
    }
)

Results in Yoda said "anger leads to hate.". At least in chrome.

My question is where is this defined? It definitely doesn't seem standardised.
It appears to be always the last parameter, after string.

I'd like to know if it's an upcoming standard, or something whacky the chrome devs have temporarily that I accidentally discovered, and it'll disappear :(

Hashbrown
  • 12,091
  • 8
  • 72
  • 95
  • Perhaps this will change when Firefox fixes [bug 1225665](https://bugzilla.mozilla.org/show_bug.cgi?id=1225665). I imagine having access to the named capture groups is intended to be in the standard, otherwise putting named capture groups in the standard would be somewhat pointless! – Matt Ellen Feb 05 '20 at 10:57
  • 1
    That is standard though and firefox is just noncompliant. Im asking specifically about receiving them in `replace()`, for which I cant even find a proposal, let alone a standard – Hashbrown Feb 05 '20 at 23:28

1 Answers1

2

The linked MDN documentation from the question now describes this new parameter, and explicitly defines exactly what was observed:

The function has the following signature:

function replacer(match, p1, p2, /* …, */ pN, offset, string, groups) {
  return replacement;
}

...

groups

An object whose keys are the used group names, and whose values are the matched portions (undefined if not matched). Only present if the pattern contains at least one named capturing group.

The exact number of arguments depends on whether the first argument is a RegExp object — and, if so, how many capture groups it has.


What's interesting is the browser compatibility section at the bottom makes no effort to differentiate between this new feature (which didn't work in Firefox at the time), simply saying "Firefox 1 full support" even though other mdn articles are usually very good at exhaustively listing browsers and at what version they each supported all the different sub-features separately.

Hashbrown
  • 12,091
  • 8
  • 72
  • 95
  • To be fair about the compatibility section, mozilla isn't preferring FF, and there are options for contributing, or reporting a problem with the content. Chrome 1 (from 2008) is also listed, which certainly didn't support it either, as https://github.com/tc39/proposal-regexp-named-groups#replacement-targets, the feature in question, is from 2017. As a general note, while the MDN is useful, it is not authorative. When talking about "standardized", the authority is the spec, https://tc39.es/ecma262/, although even that has issues, most notably TCO working nowhere but safari, for complex reasons. – ASDFGerte Sep 19 '22 at 14:48
  • 1
    (and for those who don't want to search, the related part is https://tc39.es/ecma262/#sec-regexp.prototype-@@replace, "iv. If namedCaptures is not undefined, then 1. Append namedCaptures to replacerArgs.") – ASDFGerte Sep 19 '22 at 14:50
  • Mm, I wasn't implying the mdn was preferencing FF, it's just the only one I remember not working at the time (as I mentioned it worked only in chrome at the time). It's a given it didn't work in the other browsers (but in many ways FF was [and is] known for being on par with chrome, which makes it specifically notable at the time of writing) yet the table expresses only when the bare minimum of `replace` was introduced. Which for supporting what the page references now, FF is the most-obviously incorrect at "version 1", that's all. Thanks for the ecma! – Hashbrown Sep 19 '22 at 15:51