JavaScript の テンプレートリテラル を極める！


テンプレートリテラルとは、*ECMAScript 6* で新しく使えるようになった構文のひとつです。
言わばヒアドキュメントのようなものです。めちゃくちゃ便利です！
~~2015年8月現在、Google Chrome と Firefox の最新版では既に使えるようになっています。~~
2016年9月現在、Edgeでも使えるようになっており、Google Chrome や Firefox も含めたほとんどのモダンブラウザで利用可能です。
（残念ながらモバイルブラウザではまだ非対応のこともあるので、要注意です。）

# 基本

この内容を知っているだけでもカナリ使えます！

## バッククオート（``` `～` ```）で囲む！

```js
var a = "ジャバスクリプト";
var b = `ジャバスクリプト`;
console.log( a === b ); // true
console.log( b ); // ジャバスクリプト
```

つまり、シングルクオート（`'text'`） や ダブルクオート（`"text"`） と基本は同じです！

## 改行をそのまま書ける！

```js
var a = "ジャバ\nスクリプト";
var b = `ジャバ
スクリプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ⏎スクリプト
```

`` "\n" `` の代わりに、`` `⏎` `` と書くことができるということです。

### もちろん、今までのエスケープも併せて使える！

```js
var a = "ジャバ\nスク\nリプト";
var b = `ジャバ\nスク
リプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ⏎スク⏎リプト
```
```js
var a = "ジャバ\\スク\nリプト";
var b = `ジャバ\\スク
リプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ\スク⏎リプト
```

`` `\n` `` と書くことも、`` `⏎` `` と書くこともできるということです。

## エスケープせず、そのまま文字にしたいなら`String.raw`！

`` `～` ``の中では`\n`みたいなエスケープが可能ですが、場合によっては余計なお世話に感じることもあります。
**エスケープせず本当にそのままの文字が欲しい場合**は、**`` String.raw`～` ``** を使います。

```js
var a = "ジャバ\\スク\\nリプト";
var b = String.raw`ジャバ\スク\nリプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ\スク\nリプト
```

つまり、`"\\n"` のようにエスケープする必要があるところを、**`` String.raw`\n` `` のようにそのまま書ける**ということです！

## `` `${～}` `` の中には、変数や計算式を入れることができる！

```js
var foo = "--";
var a = "ジャバ" + foo + "スク" + (111+222) + "リプト";
var b = `ジャバ${foo}スク${111+222}リプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ--スク333リプト
```

つまり、**`+`演算子 を使わずに文字列を繋げていく**ことができます。
`` `${～}` `` の中には、式であれば何でも入れることができます！

### でも `${}` を文字として入れたいときもある。

そんな時は、`` `\${}` `` や `` `$\{}` `` のようにエスケープします。

```js
var a = "ジャバ${foo}スクリプト";
var b = `ジャバ\${foo}スクリプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ${foo}スクリプト
```

## もちろん、`` String.raw`～` `` と `` `${～}` `` を両方使うことも可能！

```js
var foo = "--";
var a = "ジャバ" + foo + "スク\\リプト";
var b = String.raw`ジャバ${foo}スク\リプト`;
console.log( a === b ); // true
console.log( b ); // ジャバ--スク\リプト
```


# 発展

この内容を知っていればもっと便利！
基本はバッチリという人はぜひこっちもマスターしてください！

## `` String.raw`～` `` の正体

**`String.raw` はただの関数です**。

**`func()`** は関数を実行する構文なのと同様に、
**``func`～` ``** もまた、関数を実行する構文なのです。
（この構文は、タグ付きテンプレートリテラル（*Tagged Templates*）と言います。）

ただし、**``func`～` `` のように関数を実行した場合、渡される引数がちょっと変わっています**。
どんな引数が渡されるのか、以下を例にとってみてみましょう。

```js
function tag(){
  console.log(arguments);
}
tag`\\ジャバ${true}スク${1+2}リプト`;
/*
  0: ["\ジャバ", "スク", "リプト", raw: ["\\ジャバ", "スク", "リプト"]]
  1: true (Boolean型)
  2: 3 (Number型)
*/
```

**第1引数には文字列の配列**が入っています。**リテラル中に `${～}` が含まれる場合、`${～}` の前後で分割されます**。
さらに**その配列の rawプロパティ には、エスケープされていない文字列の配列**が入っています。
**第2引数以降には `${～}` の中身で評価された式の値**が順に入っています。（String型に変換されていない点に注意です。）

つまり、`String.raw` を自前で定義すると以下のようになります。

```js
String.raw = function(strings){
	var str = "";
	var raws = strings.raw;
	var subs = Array.prototype.slice.call(arguments, 1);
	for(var i=0;i<raws.length;i++){
		str += raws[i];
		if(i < raws.length - 1) str += subs[i];
	}
	return str;
}; 
```

```js
String.raw = ({raw:raws}, ...subs) => {
	let str = "";
	for(let s of raws) str += s + (subs.length ? subs.shift() : "");
	return str;
}; 
```

## 自分で定義した関数でタグ付きテンプレートリテラルを使ってみる

HTML のエスケープとかに使えます。

```js
function tagHtmlEscape(strings){
	var str = "";
	var subs = Array.prototype.slice.call(arguments, 1);
	for(var i=0;i<strings.length;i++){
		str += strings[i];
		if(i < strings.length - 1) str += subs[i].replace(/&/g, "&amp;").replace(/</g, "&lt;");
	}
	return str;
}; 
var userinput = '<script>alert("XSSテスト");</script>';
var message = tagHtmlEscape`<p>${userinput}</p>`;
console.log(message); // "<p>&lt;script>alert("XSSテスト");&lt;/script></p>"
```

# マニアック

## `` String.raw`～` `` の弱点

エスケープせずそのままの文字を表現できるという魅力がありますが、全ての文字を表現できるわけではありません。
例えば、文字列の最後が `\` で終わるようにはできません。

```js:エラー！
var b = String.raw`ジャバ\スク\\リプト\`;
```

これは、`` `ジャバ\スク\\リプト\` `` をテンプレートリテラルと見なした際、終わりの `` \` `` がエスケープされているとみなされ、テンプレートリテラルが終わらないからです。

以下のように書けば解決しますが、あまりスマートではありませんね…。

```js
var b = String.raw`ジャバ\スク\\リプト` + "\\";
```

ES6 のテンプレートリテラル、改善の余地があると感じます。

## タグ付きテンプレートリテラルで渡される第一引数の性質

タグ付きテンプレートリテラル（`` func`～` ``）で渡される第一引数には、以下の変わった性質があります。
1. プロパティの追加・変更・削除が不可能
2. rawの文字列の配列の要素がすべて一致する場合、何度実行しても同じ配列オブジェクトを参照する

以上の性質を示すコードが以下になります。

```js
function tag(ary){ return ary; }
var a = tag`ジャバ${123}スクリプト`;
var b = tag`ジャバ${456}スクリプト`;
console.log(a); // ["ジャバ", "スクリプト", raw: ["ジャバ", "スクリプト"]]
a[0] = "JAVA"; // 変更不可
delete a[1]; // 削除不可
a[2] = "！"; // 追加不可
console.log(a); // ["ジャバ", "スクリプト", raw: ["ジャバ", "スクリプト"]]
console.log(a === b); // 同じオブジェクトを指している
```

## 改行コードは気にしなくていい

改行コードには、CR、LF、CR+LF の3種類があります。
それでは、`` `～` `` の中に改行を入れた時、改行コードを意識しないといけないのかというと、その必要はありません。
**`` `～` `` の中の改行は自動的に全て LF に統一されます**。

```js
var a = eval("`ジャバ\rスクリプト`");
var b = eval("`ジャバ\nスクリプト`");
var c = eval("`ジャバ\r\nスクリプト`");
var s = "ジャバ\nスクリプト";
console.log(a === s, b === s, c === s); // true, true, true
```

もっと細かな話をすると、実は HTML 内に書いた改行コードは全てパースする時点で LF に統一されるのですが…。これはまた別の機会に。

## ショートコーディング

タグ付きテンプレートリテラルの性質を使えば、面白いショートコーディングができます。

```js
console.log( "abcde".split`` ); // .split("") より2文字短い
console.log( [1,2,3].join`` ); // .join("") より2文字短い
console.log( "aabbcc".split`b`.join`B` ); // .replace(/b/g,"B") より 1文字短い
console.log( "abcde".match`b.d` ); // .match(/b.d/) より2文字短い
console.log( [1,2,3].push`` ); // .length+1 より 2文字短い
```