JavaScriptのString.prototype.replaceAllについて

 

 

要約

来年、2021年のどこかで、JavaScriptのString.prototypeにreplaceAll関数が追加される予定です。

2017年11月からTC39の会議で会話が続けられてきました。

 

以下の挙動になります。


'aabbcc'.replaceAll('b','_');
// -> 'aa__cc'

'q=query+string+parameters'.replaceAll('+',' ')
// -> 'q=query string parmenters'

 

developer.mozilla.orgでは既にドキュメントが公開されています。

 

各ブラウザのサポート予定(2020年7月現在)

 

Chrome 85以上
FireFox 77以降
Opera 予定なし
Safari 13.1以降

 

上記のように主要ブラウザはほぼサポートを予定しています。

何か足りない?主要ブラウザは揃っていますね。

 

 

 

 

書いた人

・・・・・・・・・・・。
グッチです。

バックエンド
エンジニア

グッチ

ロジカルスタジオでバックエンドエンジニアをしております。

バックエンド
エンジニア

グッチ

・・・・・・・・・・・。
グッチです。

バックエンド
エンジニア

グッチ

 

 

 

 

 

説明

 

replace関数の問題

'たけ〇この里は美味しい。たけ〇この里最高!たけ〇この里が無いと生きていけない'.replace('たけ〇この里','き〇この山');

見て!String.prototype.replace関数ちゃんがこの世全ての「たけ〇この里」を消し去ろうとしているよ。かわいいね。

 

> 'き〇この山は美味しい。たけ〇この里最高!たけ〇この里が無いと生きていけない'

第一引数を正規表現にしてグローバルフラグを付けなかったので、「たけ〇この里」を駆逐できませんでした。

 

実装者のせいです。

 

あ〜あ。

 

 

 

 

何がいけなかったのでしょうか

ご存知のようにreplace関数は以下のように書かなければ全置換ができません。

 

'abcabc'.replace(/b/g, 'x');
// -> 'axcaxc'

 

しかし引数に正規表現を取ることは様々な問題が付いて回ります。

正規表現に慣れていない実装者は常に一定数存在しますし、レビュワーがエスケープ処理の必要な文字について常に完璧に暗記している保証も有りません。

 

一部の人々は、1つの問題に直面したとき「知ってる。正規表現を使えば良い」と言って2つの問題を抱え込みます。

Some people, when confronted with a problem, think “I know, I’ll use reg-ular expressions.” Now they have two problems

Jamie Zawinskiの言葉

 

提案内容

 

stackoverflowで活発なやり取りがあった後、tc39にreplaceAllの提案がされました。

その動機について以下のように述べられています。

 

動機

 

現在、グローバル正規表現を使用せずに文字列内の部分、文字列のすべてのインスタンスを置き換える方法はありません。

これを実現する最も一般的な方法は、グローバル正規表現を使用することです。

 


const queryString = 'q=query+string+parameters';
const withSpaces = queryString.replace(/\+/g, ' ');
 

 

このアプローチには、特別なRegExp文字をエスケープする必要があるという欠点があります。’+’がエスケープされていることに注意してください。

代替の解決策は、以下のようにString#splitとArray#joinを組み合わせることです。

 


const queryString = 'q=query+string+parameters';
const withSpaces = queryString.split('+').join(' ');
 

 

このアプローチはエスケープを回避しますが、文字列をパーツの配列に分解して結合するためのオーバーヘッドを伴います。

 

提案されたソリューション

 

String.prototypeに新しいメソッド(replaceAll)を追加することを提案します。これにより、開発者はこの共通の基本的な操作を簡単に実行できます。

 


const queryString = 'q=query+string+parameters';
const withSpaces = queryString.split('+').join(' '); 
 

 

また、特殊な正規表現文字をエスケープする必要がなくなります。

 

感想

実は今年、同じString.prototypeにmatchAll関数のサポートが各ブラウザで開始されています。

正規表現を引数にとるインタフェースについて、様々な見直しが進んでいるのかもしれません。

補足

[*1]TC39: Javascriptの仕様を策定している委員会。

[*2]グローバルフラグ: 正規表現は/(パターン)/(フラグ)の記法を使用するが、この(フラグ)にg(グローバルフラグ)を付けるとマッチ処理が全文に適用される

ところで

弊社ロジカルスタジオでは、ストレスの少ない職場環境について活発なやり取りと提案を求めております!

コントリビュート頂ける方!ぜひ採用サイトからご応募ください!