【JSリファレンス】get RegExp[@@species]

更新日:2024/06/14

get RegExp[ @@species ]は、RegExpコンストラクターアクセサプロパティです。
このプロパティはセッターが定義されていないため、取得のみ行えます。

@@speciesは仕様上の表記です。
プログラムコード上ではSymbol.speciesに置き換えられます。

[ Symbol.species ]は、インスタンスを返すprototypeメソッド等で使用するコンストラクターがセットされています。
class構文等で[Symbol.species]を上書きすることでメソッド内で生成されるオブジェクトを変更できます。

RegExp[Symbol.species]は、this値を返します。

 

■備考

RegExpにインスタンスを返すprototypeメソッドはありません。
RegExp[Symbol.species]は、下記メソッドの内部処理のみで使用されています。

RegExp[Symbol.species]を使用しているメソッド
RegExp.prototype[@@matchAll]()
RegExp.prototype[@@split]()

 

■使用例

RegExp.prototype[@@matchAll]()は、[Symbol.species]で生成したオブジェクトのexecメソッドを呼び出します。
次のコードは、RegExp.prototype[@@matchAll]()が呼び出すexecメソッドを独自のものに変更しています。


const MyRegExp = class extends RegExp{
    constructor(pattern, flags){
        super(pattern, flags);
    }
    static get [Symbol.species](){
        return this;
    }
     // 文字列を2文字単位で返す
    exec( text ){
        const lastIndex = this.lastIndex;
        if( text.length <= lastIndex ) return null;
        this.lastIndex += 2;
        return [text.substring( lastIndex , lastIndex + 2)]
    }
}

const rg1 = new MyRegExp();

console.log([...rg1[Symbol.matchAll]("123456")]);
// [ [ '12' ], [ '34' ], [ '56' ] ]

上のコードはexecメソッドがmatchAll専用になってしまうため、実際に同様の処理を行うならRegExp.prototype[@@matchAll]()を上書きします。

const MyRegExp = class extends RegExp{
    // ・・・省略

    // 文字列を2文字単位で返す
    *[Symbol.matchAll](text){
        for( let count = 0; count < text.length ; count += 2 ){
            yield [text.substring( count , count + 2 )];
        }
    }
}
const rg1 = new MyRegExp();
console.log([...rg1[Symbol.matchAll]("123456")]);
// [ [ '12' ], [ '34' ], [ '56' ] ]

RegExp.prototype[@@split]()は、RegExpオブジェクトをyフラグを付加して生成し、execメソッドを呼び出します。
yフラグはlastIndexの位置で照合を行い、その位置でマッチングしないときはnullを返します。

const MyRegExp = class extends RegExp{
    constructor(pattern, flags){
        super(pattern, flags);
    }
    static get [Symbol.species](){
        return this;
    }
      // 3文字目で分割
    exec( text ){
        const lastIndex = this.lastIndex;
        if(  lastIndex % 3 !== 2 ) return null;

          // マッチ文字数分lastIndexを進める
        this.lastIndex ++;

          // [0]は結果に反映されない
          // [1]以降は反映される
        return return ["",text.substring(lastIndex,lastIndex+1)];
    }
}

const rg1 = new MyRegExp();

console.log("12345678".split(rg1));
 // [ '12', '3', '45', '6', '78' ]

上のコードはexecメソッドがsplit専用になってしまうため、実際に同様の処理を行うならRegExp.prototype[@@split]()を上書きします。

const MyRegExp = class extends RegExp{
    // ・・・省略

    // 3文字目で分割
    [Symbol.split](text){
        return [...text].reduce( (pre,c,index)=>{
            index % 3 !== 1 ? pre.push(c) : pre[pre.length-1] += c;
            return pre;
       },[]);
    }
}

const rg1 = new MyRegExp();
console.log(rg1[Symbol.split]("12345678"));
 // [ '12', '3', '45', '6', '78' ]

更新日:2024/06/14

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://jsref.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。