質問:
この文字列があるとして:
以下をすると:
上の文字列で最初のabc
だけを取り除いているみたいだけど、どうやったらすべてのabs
を置き換えることができる?
回答1:
それをするには基本的に2つの方法があるよ。
注意: 一般的に、built-inのプロトタイプをJavaScriptで拡張することは一般的に推奨されてないよ。僕はString
built-inプロトタイプに対する仮想的な標準メソッドの実装例を見せるために、Stringプロトタイプの拡張例としてこれを書いてる。
正規表現ベースの実装
|
Splitおよびjoinを用いた実装
|
効率の面で正規表現がどのように裏で何をやってるか昔はあまり知らなかったから、僕はsplitとjoinを使った実装を(パフォーマンスを考慮せずに)よく使ってきた。今はどっちがどのぐらい効率がいいかを調べるたいと思った時だけ使うようにしてる。
僕のChromeのWindows 8マシンでは、正規表現ベースの実装が一番速かった。splitとjoinの実装ではそれより53%遅くなった。
この2つを実行しているベンチマークを見てみて。
注意すべきは、search
が通常の特殊文字として予約されている特定の文字式を含む場合、正規表現ベースの実装にはちょっと問題がある。この実装は、呼び出し側がそういう文字列をあらかじめエスケープするか、正規表現(MDN)テーブル内の文字を含まない文字列だけを渡しますことを前提としてる。
MDNは、文字列をエスケープするための実装も提供してる。これも RegExp.escape(str)
として標準化されてたらよかったけど、まあ、それは
実現してない:
|
String.prototype.replaceAll
の実装の中でescapeRegExp
を呼び出すこともできる。でも僕はこれがどのくらいパフォーマンスに影響するか分からない(英数字の文字列のようにエスケープが必要でない文字列に対してすらも)。
回答2:
|
それか
|
さらに単純化すれば、
|
注意: 正規表現には特別な(メタ)文字が含まれてる。だから、それらの文字をエスケープすること無しにfind
関数の引数を盲目的に渡してしまうのは危険だ。これはMozilla Developer Networkの正規表現に関するJavaScriptガイドでカバーされてる。 そこでは次のユーティリティ関数が例示されてる:
|
だから、replaceAll()
関数を上記より安全にするためにescapeRegExp
もインクルードすると、以下のようになる:
|
Source: How to replace all occurrences of a string in JavaScript?