🎄
ENCA 23日目: RegExp.prototype.replace のキャプチャで2桁から1桁にフォールバックする仕様修正
RegExp.prototype.replace
と正規表現
文字列を置換する際に用いる RegExp.prototype.replace
は第一引数に正規表現[1]を受け取ることが出来ます。その場合第二引数には文字列か函数を渡すことでマッチした部分文字列を置き換えます。文字列を使った例が以下のようになります。
console.log("foo".replace(/foo/u, "bar")); // "bar"
console.log("foo".replace(/(foo)/u, "$1 $1")); // "foo foo"
console.log("foo".replace(/(?<char>o)/u, " $<char> ")); // "f o o"
さて $1
のように正規表現のキャプチャにマッチした部分を置換する場合、そもそも正規表現側に対応するキャプチャがない場合はそのまま $1
のような文字列が結果に残ります。
console.log("foo".replace(/(foo)/u, "$1 $2")); // "foo $2"
RegExp.prototype.replace
のキャプチャで2桁から1桁にフォールバックする仕様修正
RegExp.prototype.replace
の第二引数に $12
のように2桁のキャプチャ置換を指定することを考えます。この場合正規表現側のキャプチャ数によって以下のような結果になります。
// 正規表現に12個のキャプチャがあるケース
// 12番目の "J" がキャプチャされ "$12" を "J" に置換する
console.log("ABCDEFGHIJ".replace(/(A)(B)(C)(D)(E)(F)(G)(H)(I)(J)/, "$12"));
// => "J"
// 正規表現に11個のキャプチャがあるケース
// 1番目の "A" がキャプチャされ "$1" を "A" に置換する
console.log("ABCDEFGHIJ".replace(/(A)(B)(C)(D)(E)(F)(G)(H)(I)J/, "$12"));
// => "A2"
どのブラウザランタイムでもこのように2桁から1桁にフォールバックする挙動となっていましたが、仕様ではそのようなフォールバックについて記述されていませんでした。2023年9月に仕様を実態(Web Reality)に合わせようと議論され、承認されました。
-
実はネイティブの
RegExp
でなくてもSymbol.replace
メソッドを持っていればそちらが実行されます。 ↩︎
Discussion