RegExp.prototype[@@match]()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

[@@match]()RegExp インスタンスのメソッドで、 String.prototype.match() がどのように動作するのかを指定します。さらに、これが存在するかどうかが、そのオブジェクトが正規表現とみなされるかどうかにも影響します。

試してみましょう

構文

js
regexp[Symbol.match](str)

引数

str

文字列 (String) で、照合の対象となるものです。

返値

配列 (Array) で、内容はグローバル (g) フラグがあるかどうかで変わります。一致するものが見つからなければ null になります。

  • g フラグが使用された場合は、この正規表現全体に一致したすべての結果となりますが、キャプチャグループは含まれません。
  • g フラグが使用されなかった場合は、最初に一致したもの全体と、関連するキャプチャグループが返されます。この場合、 match()RegExp.prototype.exec() (一部の追加のプロパティを配列で含む)の結果と同じになります。

解説

このメソッドは、String.prototype.match() で内部的に呼び出されます。

たとえば、次の 2 つの例は同じ結果を返します。

js
"abc".match(/a/);

/a/[Symbol.match]("abc");

正規表現がグローバル(g フラグ付き)である場合、この正規表現の exec() メソッドは、 exec()null を返すまで繰り返し呼び出されます。そうでない場合、 exec() は一度だけ呼び出され、その結果が @@match の返値となります。

@@matchexec()null が返るまで呼び出し続け、最後の照合に失敗すると自動的に正規表現の lastIndex を 0 にリセットします。しかし、正規表現が粘着的であるもののグローバルではない場合、 lastIndex はリセットされません。この場合、 match() を呼び出すたびに異なる結果を返すかもしれません。

js
const re = /[abc]/y;
for (let i = 0; i < 5; i++) {
  console.log("abc".match(re), re.lastIndex);
}
// [ 'a' ] 1
// [ 'b' ] 2
// [ 'c' ] 3
// null 0
// [ 'a' ] 1

正規表現が粘着的かつグローバルな場合、粘着的な照合、つまり lastIndex 以降の照合は行われません。

js
console.log("ab-c".match(/[abc]/gy)); // [ 'a', 'b' ]

もし現在の照合が空文字列であったとしても、 lastIndex は進みます。正規表現が Unicode 対応モードであれば、Unicode のコードポイント 1 つ分進みます。そうでなければ、 UTF-16 コード単位分進みます。

js
console.log("😄".match(/(?:)/g)); // [ '', '', '' ]
console.log("😄".match(/(?:)/gu)); // [ '', '' ]

このメソッドは RegExp サブクラス内で照合の動作をカスタマイズするために存在します。

さらに、@@match プロパティはオブジェクトが正規表現であるかどうかをチェックするために使われます。

直接呼び出し

このメソッドは、ほとんど String.prototype.match() と同じ方法で使用することができますが、 this と引数の並び順が異なります。

js
const re = /[0-9]+/g;
const str = "2016-01-02";
const result = re[Symbol.match](str);
console.log(result); // ["2016", "01", "02"]

サブクラスで @@match を使用

RegExp のサブクラスは、既定の動作を修正するために [@@match]() メソッドをオーバーライドできます。

js
class MyRegExp extends RegExp {
  [Symbol.match](str) {
    const result = RegExp.prototype[Symbol.match].call(this, str);
    if (!result) return null;
    return {
      group(n) {
        return result[n];
      },
    };
  }
}

const re = new MyRegExp("([0-9]+)-([0-9]+)-([0-9]+)");
const str = "2016-01-02";
const result = str.match(re); // String.prototype.match は re[@@match] を呼び出す
console.log(result.group(1)); // 2016
console.log(result.group(2)); // 01
console.log(result.group(3)); // 02

仕様書

Specification
ECMAScript Language Specification
# sec-regexp.prototype-%symbol.match%

ブラウザーの互換性

BCD tables only load in the browser

関連情報