---
title: 樣板字面值
slug: Web/JavaScript/Reference/Template_literals
tags:
  - ECMAScript 2015
  - Guide
  - JavaScript
  - String
  - Template Strings
  - Template literals
  - Template string
  - strings
translation_of: Web/JavaScript/Reference/Template_literals
---
<div>{{JsSidebar("More")}}</div>

<p>樣板字面值(Template literals)是允許嵌入運算式的字串字面值(string literals)。你可以透過樣板字面值來使用多行字串及字串內插(string interpolation)功能。他們在 ES2015 規範的先行版本中被稱為「樣板字串(template strings)」。</p>

<h2 id="語法">語法</h2>

<pre class="syntaxbox">`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tag `string text ${expression} string text`
</pre>

<h2 id="描述">描述</h2>

<p>樣板字面值(Template literals)被反引號(back-tick,<a href="https://zh.wikipedia.org/wiki/%E9%87%8D%E9%9F%B3%E7%AC%A6">重音符號</a>):` ` 字元封閉,代替了雙或單引號。樣板字面值可以包含由錢字元及花括號所構成(<code>${expression}</code>)的佔位符(placeholders)。這個在佔位符中的運算式以及在它們之間的文字會被傳入一個函式。預設函式只是將這些部分組合成一個單一的字串。如果在樣板字面值前有一個運算式(<code>tag</code> here),則此樣板字串被稱為「標籤樣板字面值(tagged template literal)」。在此情況下,標籤運算式(通常是一個函式)會被呼叫來處理樣板字面值,讓你可以在函式回傳之前進行操作。要在樣板字面值中跳脫一個反引號,可以於反引號前加上一個反斜線(backslash)<strong>\ </strong>。</p>

<pre class="brush: js">`\`` === '`' // --&gt; true</pre>

<h3 id="多行字串">多行字串</h3>

<p>任何在樣板字面值中使用、插入的換行符號,都是樣板字面值的一部份。在普通的字串中,我們需要使用如下的語法以達到換行的效果:</p>

<pre class="brush: js">console.log('string text line 1\n' +
'string text line 2');
// "string text line 1
// string text line 2"</pre>

<p>但使用樣板字面值,你只需要撰寫如下所示的程式碼,就能達到同樣的效果:</p>

<pre class="brush: js">console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"</pre>

<h3 id="運算式內插">運算式內插</h3>

<p>要在普通的字串中內嵌運算式,我們必須使用如下語法:</p>

<pre class="brush: js">var a = 5;
var b = 10;
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
// "Fifteen is 15 and
// not 20."</pre>

<p>現在有了樣板字面值,我們可以用一種更優雅的寫法,讓語法更具可讀性:</p>

<pre class="brush: js">var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."</pre>

<h3 id="巢狀樣板">巢狀樣板</h3>

<p>In certain times, nesting a template is the easiest and perhaps more readable way to have configurable strings. Within a backticked template it is simple to allow inner backticks simply by using them inside a placeholder <code>${ }</code> within the template. For instance, if condition a is true: then return this templated literal.</p>

<p>In ES5:</p>

<pre class="brush: js">var classes = 'header'
classes += (isLargeScreen() ?
   '' : item.isCollapsed ?
     ' icon-expander' : ' icon-collapser');
</pre>

<p>In ES2015 with template literals and without nesting:</p>

<pre class="brush: js">const classes = `header ${ isLargeScreen() ? '' :
    (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;</pre>

<p>In ES2015 with nested template literals:</p>

<pre class="brush: js">const classes = `header $<strong>{</strong> isLargeScreen() ? '' :
 `icon-${item.isCollapsed ? 'expander' : 'collapser'}`<strong> </strong><strong>}`</strong>;</pre>

<h3 id="標籤樣板字面值">標籤樣板字面值</h3>

<p>標籤樣板字面值是一種更高級的樣板字面值形式,允許你透過標籤函數操作樣板字面值的輸出。標籤函數的第一個參數是一字串陣列,其餘參數則是處理過的表達式。最終,你可以返回一個經處理後的字串,甚至是完全不一樣的東西(如下述第二個範例中)。標籤函數的名稱可以是任何你想要的。</p>

<pre class="brush: js">var person = 'Mike';
var age = 28;

function myTag(strings, personExp, ageExp) {

  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // var str2 = strings[2];

  var ageStr;
  if (ageExp &gt; 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  return str0 + personExp + str1 + ageStr;

}

var output = myTag`that ${ person } is a ${ age }`;

console.log(output);
// that Mike is a youngster</pre>

<p>標籤函數不一定要回傳一個字串,如下列範例:</p>

<pre class="brush: js">function template(strings, ...keys) {
  return (function(...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function(key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join('');
  });
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure('Y', 'A');  // "YAY!"
var t2Closure = template`${0} ${'foo'}!`;
t2Closure('Hello', {foo: 'World'});  // "Hello World!"
</pre>

<h3 id="原始字串">原始字串</h3>

<p>標籤函數的第一個參數,帶有一個特殊的屬性「 <code>raw</code> 」,允許你獲取原始輸入的、未處理任何<a href="/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Using_special_characters_in_strings">轉義序列</a>的字串值。</p>

<pre class="brush: js">function tag(strings) {
  console.log(strings.raw[0]);
}

tag`string text line 1 \n string text line 2`;
// logs "string text line 1 \n string text line 2" ,
// including the two characters '\' and 'n'
</pre>

<p>此外, 使用 {{jsxref("String.raw()")}} 方法建立的原始字串,也與預設的樣板函數和字串串接會建立的字串相同。 </p>

<pre class="brush: js">var str = String.raw`Hi\n${2+3}!`;
// "Hi\n5!"

str.length;
// 6

str.split('').join(',');
// "H,i,\,n,5,!"
</pre>

<h3 id="標籤樣板字面值和跳脫序列">標籤樣板字面值和跳脫序列</h3>

<p>在 ES2016 的規範中,標籤樣板字面值遵守下列跳脫序列(escape sequences)規則:</p>

<ul>
 <li>萬國碼 (Unicode) 跳脫序列由 "\u" 作為開頭, 例: <code>\u00A9</code></li>
 <li>萬國碼位 (Unicode code point) 由 "\u{}" 作為開頭, 例: <code>\u{2F804}</code></li>
 <li>十六進位制碼由 "\x" 作為開頭, 例: <code>\xA9</code></li>
 <li>十進位制碼由 "\" 作為開頭, 例: \251</li>
</ul>

<p>這表示像是下述的標籤樣板字面值是有問題的,因為根據 ECMAScript 規範,一個語法分析器會嘗試以萬國碼轉義序列去解析它,然後發現序列有誤:</p>

<pre class="brush: js">latex`\unicode`
// Throws in older ECMAScript versions (ES2016 and earlier)
// SyntaxError: malformed Unicode character escape sequence</pre>

<p>Tagged template literals should allow the embedding of languages (for example <a href="https://en.wikipedia.org/wiki/Domain-specific_language">DSLs</a>, or <a href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a>), where other escapes sequences are common. The ECMAScript proposal <a href="https://tc39.github.io/proposal-template-literal-revision/">Template Literal Revision</a> (stage 4, to be integrated in the ECMAScript 2018 standard) removes the syntax restriction of ECMAScript escape sequences from tagged template literals.</p>

<p>However, illegal escape sequence must still be represented in the "cooked" representation. They will show up as {{jsxref("undefined")}} element in the "cooked" array:</p>

<p>l be represented in the "cooked" representation. They will show up as {{jsxref("undefined")}} element in the "cooked" array:</p>

<p> </p>

<pre class="brush: js">function latex(str) {
 return { "cooked": str[0], "raw": str.raw[0] }
}

latex`\unicode`

// { cooked: undefined, raw: "\\unicode" }</pre>

<p>Note that the escape sequence restriction is only dropped from <em>tagged</em> template literals and not from <em>untagged</em> template literals:</p>

<pre class="brush: js example-bad">let bad = `bad escape sequence: \unicode`;</pre>

<h2 id="規範">規範</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-template-literals', 'Template Literals')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Initial definition. Defined in several section of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-template-literals">Template Literals</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-tagged-templates">Tagged Templates</a></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-template-literals', 'Template Literals')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>Defined in several section of the specification: <a href="https://tc39.github.io/ecma262/#sec-template-literals">Template Literals</a>, <a href="https://tc39.github.io/ecma262/#sec-tagged-templates">Tagged Templates</a></td>
  </tr>
  <tr>
   <td><a href="https://tc39.github.io/proposal-template-literal-revision/">Template Literal Revision</a></td>
   <td>Stage 4 draft</td>
   <td>Drops escape sequence restriction from tagged template literals</td>
  </tr>
 </tbody>
</table>

<h2 id="瀏覽器相容性">瀏覽器相容性</h2>

<div>


<p>{{Compat("javascript.grammar.template_literals")}}</p>
</div>

<h2 id="參見">參見</h2>

<ul>
 <li>{{jsxref("String")}}</li>
 <li>{{jsxref("String.raw()")}}</li>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar">Lexical grammar</a></li>
 <li><a href="https://gist.github.com/WebReflection/8f227532143e63649804">Template-like strings in ES3 compatible syntax</a></li>
 <li><a href="https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2/">"ES6 in Depth: Template strings" on hacks.mozilla.org</a></li>
</ul>