WebDesign Dackel

JavaScriptで「どシンプル」なテンプレート文字列の展開を実装する

JavaScriptで「どシンプル」なテンプレート文字列の展開を実装する

Hatena0
Google+0
Pocket0
Feedly0

はじめに

JadeEJSなどのテンプレートエンジンを導入するほどでもなく、underscore.js(lodash.js)を導入していない場合に使える、「どシンプル」なテンプレート文字列の展開をご紹介します。

実際にどんな内容か、具体例をあげるとこんな感じです。

var text = "My name is ${name}";
console.log( template(text, {name: "Bob"}) );
// => My name is Bob

引数にテンプレート文字列とオブジェクトを受け取って、文字列内の${}で括られたキーに対応する値を展開する、よくみるやつになります。

今回は上記でいうtemplate関数の実装方法についてです。

どシンプルなtemplate関数

/**
 * テンプレート文字列を展開
 * 
 * @param string:String テンプレート文字列
 * @param values:Object 展開する値
 * @return String
 */
function template(string, values){
  return string.replace(/\$\{(.*?)\}/g, function(all, key){
    return Object.prototype.hasOwnProperty.call(values, key) ? values[key] : "";
  });
}

たった5行、短くていい感じです。
やっていることは単純で、

  1. ${}でマッチする文字列を検索
  2. ${}の中の文字列コールバックで受け取る
  3. 受け取った文字列をキーに、対応する値をチェック
    • 存在すれば、対応する値で置換する
    • 存在しなければ、空文字で置換する

となります。

実際に使ってみる

var text = "My name is ${name}";
console.log( template(text, {name: "Bob"}) );
// => My name is Bob

${name}がちゃんとBobに置き換わりました!

テンプレートの形式を指定できるようにする

上記のtemplate関数では、${}で括るのを固定していましたが、例えば%key%みたいな形式にしたいこともあると思います。

少し手を加えて、これを引数で指定できるようにしたいと思います。

/**
 * 文字列を正規表現用にエスケープ
 * @see http://phpjs.org/functions/preg_quote/
 */
function preg_quote(str, delimiter){
  return String(str).replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
}

/**
 * テンプレート文字列を展開
 * 
 * @param string:String テンプレート文字列
 * @param values:Object 展開する値
 * @param before:String("${") テンプレートの開始文字
 * @param after:String("}") 終了文字
 * @return String
 */
function template(string, values, before, after){
  before = preg_quote(before || "${");
  after = preg_quote(after || "}");

  return string.replace(new RegExp(before + "(.*?)" + after, "g"), function(all, key){
    return Object.prototype.hasOwnProperty.call(values, key) ? values[key] : "";
  });
}

template関数の3つ目の引数で開始文字、4つ目の引数で終了文字を指定できるようにしてみました。デフォルトでは先ほどの${}が使用されます。

また、正規表現を使った検索を行うので、変なマッチング起こらないようにこれらをエスケープする必要があります。
そのため、PHPではおなじみのpreg_quote関数を追加してみました。(ソースはphpjsのものを使用しています。)

実際に使ってみる

console.log( template("My name is ${name}", {name: "Bob"}) );
// => My name is Bob

console.log( template("My name is %name%", {name: "Bob"}, "%", "%") );
// => My name is Bob

%%で括った場合にも対応出来ました!

まとめ

このくらいのものなら、TypeScriptCoffeeScriptES6に準規したトランスパイラなんか使っていればあんまり必要無いかもしれませんが、ちょっとしたコードにはまだまだ使えるかもです。

先日コードを書いていて、「あれ?これ前にも書いたな??」ってなったので、またそうならないために記事にしてみました。