2021年12月6日 JavaScript (JS Primer) String.raw
String.rawメソッド
String.raw()は、テンプレートリテラル構文から、文字列を取得するメソッドです。 この関数は、テンプレート文字列の生の文字列形式を取得するために使用されます。つまり、置換 (例えば ${foo}) は行われますが、エスケープ (例えば \n) は実行されません。
通常だとテンプレートリテラル構文の中でエスケープを書いたとすると
以下のようにエスケープ処理が行われてしまいます。
function tag(str) { // 引数`str`にはただの文字列が渡ってくる console.log(str); // => "template 0 literal 1" } // ()をつけて関数を呼び出す tag(`template\n ${0} literal ${1}`); 出力結果 template ${0} literal ${1}
String.rawメソッドを使用すると意図しないエスケープ処理を発生させずに生の文字列を返してくれます。
(例)
console.log(String.raw`template\n ${0} literal ${1}`); 出力結果 template\n 0 literal 1
[応用]URLエスケープ
タグ関数とreduceで文字列の結合を行っても意図した通りにURLエスケープすることが出来ます。
(例)
// 変数をURLエスケープするタグ関数 function escapeURL(strings, ...values) { console.log(strings); // => [ 'https://example.com/search?q=', '&sort=desc' ] console.log(values); // => [ 'A&B' ] return strings.reduce((result, str, i) => { console.log(result); // => https://example.com/search?q= console.log(str); // => &sort=desc console.log(i); // => 1 return result + encodeURIComponent(values[i - 1]) + str; console.log(encodeURIComponent(input)); // => A%26B }); } const input = "A&B"; // escapeURLタグ関数を使ったタグつきテンプレート const escapedURL = escapeURL`https://example.com/search?q=${input}&sort=desc`; console.log(escapedURL); // => "https://example.com/search?q=A%26B&sort=desc"
JSprimerでのコード例での引数の値をconsole.logで全て出力して、処理の流れを追ったのでそのコードを貼りました。元々のURLの一部分に対してURLエスケープの処理をした上で結合しています。 結果的に文字列と、A&BをURLエスケープした値と、文字列を結合したURLを生の文字列として返しています。
encodeURIComponent関数は引数の値をURLエスケープする関数です。
JavaScriptだと、encodeURI()と、encodeURIComponent()があります。encodeURI()は&と=、/はそのままにするバージョンで、完全なURIを受け取って、そのままURIとして使える文字列を返す想定で、encodeURIComponent()はクエリパラメータで使える安全な文字列(URIの意味を壊さない)を返します。このエントリーでは後者だけを相手にします。
[検証]String.rawメソッドを利用してURLを正しく取得する場合
const input = "A&B"; console.log(String.raw`https://example.com/search?q=${encodeURIComponent(input)}&sort=desc`); 出力結果 https://example.com/search?q=A%26B&sort=desc
車のライトの交換で例えてみました
// ライト交換するタグ関数 // 白いライトに交換するというメソッドがあると仮定します。 function changeLight(car, ...lights) { return car.reduce((a, b, c) => { return a + 白いライトに交換(lights[c - 1]) + b; }); } const yellowLight = "黄色いライト"; const changedLight = changeLight`黒のボディの${yellowLight}の車`; console.log(changedLight); // => "黒のボディの白いライトの車"
今回のタグ関数を使った処理をイメージしていたら、車の部品を分解して渡して、ある部品に変化を加えてまた返すというものが浮かんだので書きました。そしてこちらをString.rawメソッドで書くと1行が書くことができます。
console.log(String.raw`黒のボディの${白いライトに交換(yellowLight)の車}); 出力結果 "黒のボディの白いライトの車"