一.作用及び構文
テンプレート文字列は文字列の挿入を実現するために使用され、プラス記号(+)での連結よりも便利でエレガントです
`${expr}` 構文は、文字列挿入機能を提供します
注意:上記の`(バッククォート、キーボードの Esc の下にあります)はテンプレート文字列構文の一部であり、markdown の誤りではありません
P.S.筆者は最初の問題に遭遇しました。バッククォートと markdown 構文が衝突します。2 つの選択があります。markdown 特性の多重バッククォートをコード区切り文字として使用する(2 つの連続バッククォートでコードを囲むが、筆者が使用する markdown プラグインはこの珍しい構文をサポートしていない)、または code タグを使用する。例えば上記の markdown ソースコードは<code>\`${expr}\`</code> です
例えば:
function req(user, action) {
// if !isValid
error(`user ${user} failed to do action ${action}`);
}
function error(str) {
console.log(str);
}
// test
req('Sam', 'login'); // user Sam failed to do action login
二.特徴
###1.expr は任意の合法 js 式でよく、ネストもサポート
変数、リテラル、関数呼び出しなどを含みますが、フロー制御(分岐/ループ)はサポートしないため、テンプレート文字列はテンプレートエンジンを代替できません
例えば:
// 不支持分支/循环
// console.log(`${if (2 > 1) {str}}`); // Uncaught SyntaxError: Unexpected token if
// console.log(`${for (; false;) {}}`); // Uncaught SyntaxError: Unexpected token for
var outer = 'outer';
var inner = 'inner';
var str = `
\$\{
${
outer // 变量
+ // + 拼接
`\$\{
${inner} // 插值
\}`
}
\}
`;
var h5 = document.querySelector('#h5');
var pre = document.querySelector('#pre');
h5.innerHTML = str;
pre.innerHTML = str;
表示結果は以下の通り:
// #h5
${ outer${ inner // 插值 } }
// #pre
${
outer${
inner // 插值
}
}
###3.複数行に分割して記述可能
ただし注釈(単行/多行)は文字列全体に作用するか、または結果文字列内にリテラルとして現れる可能性があります。テンプレート文字列中のすべてのスペース、改行、インデントは、生成された文字列中にそのまま出力されます(pre は他の要素と異なります)。具体的には上記の例を参照
###4.特殊文字はエスケープが必要
3 つの特殊文字[`${](正規表現形式)はエスケープが必要です。具体的には上記の例を参照
P.S.右中括弧はエスケープ不要ですが、もちろんエスケープしても間違いではありません。しかし上記 3 つは必須でエスケープする必要があります
###5.自動処理なし
安全でないタグを自動フィルタリングせず、特殊文字を自動エスケープもしません。xss 攻撃も防止する必要があります。タグテンプレート(tagged templates)を提供していますが、あまり便利ではありません
例えば:
// xss 攻击
var userInput = '<a href="" onclick="alert(\'xss attack\');">领取奖励</a>';
var input = document.querySelector('#input');
input.innerHTML = `用户输入:${userInput}`;
上記コードはリンクを生成し、クリックすると "xss attack" を alert します。タグテンプレートを通じてテンプレート文字列をカスタム処理できます。例えば安全でない文字をフィルタリング:
// 定义模板标签
function myFilter(templateData) {
var aStr = templateData; // 被${}插值分割后的字符串数组
var aRaw = templateData.raw; // 未经转义的原字符串(\n)
var aVar = Array.prototype.slice.call(arguments, 1); // 插值变量数组
console.log(aStr);
console.log(aRaw);
console.log(aVar);
// filter vars
aVar.forEach(function(item, index, arr) {
arr[index] = item.replace(/(<[^>]*>)/i, '');
});
var res = '';
var i = 0;
aStr.forEach(function(item) {
res += item;
if (aVar[i]) {
res += aVar[i++];
}
});
return res;
}
// 使用标签模板
var safeInput = document.querySelector('#safe_input');
safeInput.innerHTML = myFilter`用户输入:\n${userInput}`;
// 等价于
// safeInput.innerHTML = myFilter(['用户输入:'], userInput);
タグはテンプレート文字列の前に現れ、簡略化された関数呼び出し の一種です。テンプレートタグはコールバック関数に類似し、パラメータ templateData の形式は確定しており、パラメータからデータを取り出し、処理完了後に返すだけです
しかしテンプレートタグを定義するのはまだ面倒に感じられますが、これは非常に魅力的な特性で、強力な文字列処理ライブラリ(特殊文字のエスケープ、i18n、文字数統計など)を予感させます
###6.柔軟性
タグテンプレートの戻り値は文字列である必要はなく、任意の値 で構いません。これは単に強力な「文字列」処理ライブラリが現れるだけでなく、あらゆるライブラリがこの形式で完璧に JS 内に埋め込む ことができることを意味し、特にシェーダー言語のような現在 JS 内で形式があまり友好的でないもの……他の言語で魅力的な特性が現れた後、完璧に JS に移植でき、さらには借此で独自の言語を実装することもできます(テンプレートタグの関数本体がインタプリタです)
タグテンプレートは大きな柔軟性をもたらし、カスタムタグを使用して正規表現、DOM ツリー、画像、promises を代表とする非同期プロセス全体、JS データ構造、GL シェーダーなどを作成できます……
参考資料中の原文を引用:
标签模板以开放的姿态欢迎库设计者们来创建强有力领域特定语言。这些语言可能看起来不像 JS,但是它们仍可以无缝嵌入到 JS 中并与 JS 的其它语言特性智能交互。我不知道这一特性将会带领们走向何方,但它蕴藏着无限的可能性,这令我感到异常兴奋!
三.まとめ
テンプレート文字列は一見構文糖ですが、実は扉を開けたのであり、JS がオープンな姿勢で未来を迎えることを示しています
[先輩たちが 5 年前に議論した yield](/articles/javascript 实现 yield/) を覚えていますか?当時彼らはこのような特性をどれだけ望んでいたでしょうか。この問題を議論した初衷は JS が C# の yield 特性を獲得することを望んでいたからではありませんか?
参考資料
- 《ES6 in Depth》:InfoQ 中文站提供的免费电子书
コメントはまだありません