diff options
Diffstat (limited to 'files/zh-tw/web/javascript/reference/template_literals/index.html')
-rw-r--r-- | files/zh-tw/web/javascript/reference/template_literals/index.html | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/files/zh-tw/web/javascript/reference/template_literals/index.html b/files/zh-tw/web/javascript/reference/template_literals/index.html new file mode 100644 index 0000000000..9ed8da0437 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/template_literals/index.html @@ -0,0 +1,252 @@ +--- +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">`\`` === '`' // --> 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 > 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> |