TL; DR
Stringオブジェクトのreplace
メソッドは、第2引数に関数をとれて便利。
はじめに
JavaScriptで文字列置換したいときに、replace
メソッドをよく使います。例えば、スペースをハイフンにしたければこんな具合です。
"foo bar".replace(" ", "-") // => "foo-bar"
ただ、これだと最初にマッチしたスペースしか置換されません。
"foo bar baz".replace(" ", "-") // => "foo-bar baz"
第1引数には正規表現も書けるので、g
オプションをつけた正規表現を使えばすべてのスペースが置換できます。
"foo bar baz".replace(/ /g, "-") // => "foo-bar-baz"
できました。ここまでは単純な置換です。
置換パターン
さて、もっと込み入ったことをしたいとします。例えば、各単語をかっこで囲みたいとしましょう。"foo bar baz"
を、"(foo) (bar) (baz)"
にします。このようなマッチした文字列を使い回す置換は、置換パターンが便利です。
"foo bar baz".replace(/\w+/g, "($&)") // => "(foo) (bar) (baz)"
ここでは、マッチした文字列を表す$&
という置換パターンを使いました。
キャプチャした文字列を$1
, $2
... で参照することもできます。
"John,male\nJane,female".replace(/(\w+),(\w+)/g, "name: $1, gender: $2") // name: john, gender: male\nname: jane, gender: female
話はこれで終わりません。更に高度なことができます。
第2引数の関数指定
replace
の第2引数には関数が指定できます。第1引数がマッチするたびに呼ばれます。引数には、マッチした文字列に関する情報が入ります。
"foo bar baz".replace(/\w+/g, match => match.toUpperCase()) // => "FOO BAR BAZ"
これでもう何でもありですね。ちょっとした自作テンプレートのようなこともできます。
const bindings = {
host: 'example.com',
port: 8080
}
// キャプチャした文字列は2つ目の引数に入ります。
// 2つ以上キャプチャした場合は3つ目、4つ目…の引数に入ります。
"http://{{host}}:{{port}}".replace(/{{(\w+)}}/g, (_, key) => bindings[key]) // => "http://example.com:8080"
便利。