1

JavaScript has a regular expression class RegExp. You can create them directly re = new RegExp(...) or indirectly re = /.../

Most of the traditional methods are what I'm used to from many years of programming

const match = re.match(str);
const isMatch = re.text(str);

But today I looked for a matchAll function and to use it the syntax is this

const matches = re[Symbol.matchAll](str)

What's up with this style of finding a function? Why is it not just

const matches = re.matchAll(str);

I'm guessing there is some reason there are a several functions using this special format. What is the reasoning behind it?

const re = /a(.)b(.)c/g;
const matches = re[Symbol.matchAll]('a1b2c a3b4c a5b6c');
console.log([...matches]);
gman
  • 100,619
  • 31
  • 269
  • 393
  • When adding new facilities to JavaScript, the committee has to be careful not to break half the Internet. Old pages may have added `String.prototype` methods (it was common 10 years ago and may still be) and thus name collisions would make working pages fail with new browser releases. – Pointy Jun 23 '19 at 14:49
  • Because there's no practical way to *ensure* that new features do not introduce name collisions. The `Symbol` class is designed explicitly to address that, you can add all the random Symbol instances you want, and they're guaranteed to be distinct from any other instance. – Pointy Jun 23 '19 at 14:53
  • Right but no legacy page would be doing that, since the `Symbol` facility itself is new. New code that tried that would be "born" facing the fact that it's stepping on a built-in facility. – Pointy Jun 23 '19 at 14:55
  • lol, embarrassing – Pointy Jun 23 '19 at 15:01

1 Answers1

2

I looked for a matchAll function and to use it the syntax is re[Symbol.matchAll](str)

No. The proper syntax is to use the String matchAll method, like this:

const matches = str.matchAll(re);

What is the reasoning behind several functions using this special format?

They are following a protocol. Like the iterable protocol or the thenable protocol, they are usually used internally in some other methods/syntax and are not supposed to be called directly. Such a protocol allows for customised implementations of the feature, providing a hook to override.

In the case of Symbol.matchAll, it allows arbitrary objects to be used as matchers for strings. For example:

const integers = {
    *[Symbol.matchAll] (str) {
         for (const m of str.matchAll(/\d+/g))
             yield parseInt(m[0], 10);
    }
};

console.log(Array.from("42ab17, 2x".matchAll(integers)))

The matchAll and match symbols were introduced to allow a class that extends RegExp to override the behaviour when interacting with the respective String methods. In practice, the inheritance relationship is not enforced though, the mere existence of the symbol-keyed method is enough.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • well color me pink – Pointy Jun 23 '19 at 15:00
  • /setColor [ pink, target=@Pointy ] – Bergi Jun 23 '19 at 15:00
  • I am however a *little* surprised at adding a `String.prototype` method after almost 20 years of the Wild West. – Pointy Jun 23 '19 at 15:01
  • Does that mean [the MDN docs for String.matchAll](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll) are out of date? They don't mention `matchAll` taking anything but a `RegExp` at least as of 2019-06-23 – gman Jun 23 '19 at 15:08
  • 1
    @gman I'd rather say *incomplete*, not "out of date", since it doesn't mention this ability. However, the `matchAll` Symbol is indeed meant to be mostly placed on RegExp objects, it specifically was introduced to allow overriding `String::matchAll` behaviour for `RegExp` subclasses. – Bergi Jun 23 '19 at 15:17
  • @Bergi What syntax are you using to colour Pointy pink? I don't recognise it. I would have done something like `#Pointy { color: pink; }` :P – Clonkex Mar 07 '22 at 23:01
  • 1
    @Clonkex i guess some mix of IRC, Minecraft and Discord commands – Bergi Mar 08 '22 at 02:22