uTools-Manuals/docs/javascript/Reference/template_strings.html
2019-04-21 11:50:48 +08:00

288 lines
22 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article id="wikiArticle">
<div> </div>
<p>模板字面量 是允许嵌入表达式的字符串字面量。你可以使用多行字符串和字符串插值功能。它们在ES2015规范的先前版本中被称为“模板字符串”。</p>
<h2 id="语法" style="font-size: 2.14285714285714rem;">语法</h2>
<pre><code class="language-javascript">`string text`
`string text line 1
string text line 2`
`string text ${expression} string text`
tag `string text ${expression} string text`
</code></pre>
<h2 id="描述" style="font-size: 2.14285714285714rem;">描述</h2>
<p>模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法(<code style="font-style: normal;">${expression}</code>)的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来,如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,你都可以通过该函数来对模板字符串进行操作处理。在模版字符串内使用反引号(`)时,需要在它前面加转义符(\)。</p>
<pre><code class="language-javascript">`\`` === "`" // --&gt; true</code></pre>
<h3 id="多行字符串">多行字符串</h3>
<p>在新行中插入的任何字符都是模板字符串中的一部分,使用普通字符串,你可以通过以下的方式获得多行字符串:</p>
<pre><code class="language-javascript">console.log('string text line 1\n' +
'string text line 2');
// "string text line 1
// string text line 2"</code></pre>
<p>要获得同样效果的多行字符串,只需使用如下代码:</p>
<pre><code class="language-javascript">console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"</code></pre>
<h3 id="插入表达式">插入表达式</h3>
<p>在普通字符串中嵌入表达式,必须使用如下语法:</p>
<p> </p>
<pre><code class="language-javascript">var a = 5;
var b = 10;
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
// "Fifteen is 15 and
// not 20."</code></pre>
<p> </p>
<p>现在通过模板字符串,我们可以使用一种更优雅的方式来表示:</p>
<p> </p>
<pre><code class="language-javascript">var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."</code></pre>
<p> </p>
<h3 id="嵌套模板">嵌套模板</h3>
<p>在某些时候,嵌套模板是具有可配置字符串的最简单也是更可读的方法。 在模板中,只需在模板内的占位符 <code>${ }</code> 内使用它们,就可以轻松地使用内部反引号。 例如,如果条件 a 是真的,那么返回这个模板化的文字。</p>
<p>ES5:</p>
<pre><code class="language-javascript">var classes = 'header'
classes += (isLargeScreen() ?
'' : item.isCollapsed ?
' icon-expander' : ' icon-collapser');</code></pre>
<p>在ES2015中使用模板文字而没有嵌套</p>
<pre><code class="language-javascript">const classes = `header ${ isLargeScreen() ? '' :
(item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;
</code></pre>
<p> </p>
<p>在ES2015的嵌套模板字面量中</p>
<p> </p>
<pre><code class="language-javascript">const classes = `header ${ isLargeScreen() ? '' :
`icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;</code></pre>
<p> </p>
<p> </p>
<h3 id="带标签的模板字符串">带标签的模板字符串</h3>
<p>更高级的形式的模板字符串是带标签的模板字符串。标签使您可以用函数解析模板字符串。标签函数的第一个参数包含一个字符串值的数组。其余的参数与表达式相关。最后,你的函数可以返回处理好的的字符串(或者它可以返回完全不同的东西 , 如下个例子所述)。用于该标签的函数的名称可以被命名为任何名字。</p>
<pre><code class="language-javascript">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</code></pre>
<p class="brush: js">正如下面例子所展示的,标签函数并不一定需要返回一个字符串。</p>
<pre><code class="language-javascript">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!"</code></pre>
<h3 id="原始字符串">原始字符串</h3>
<p>在标签函数的第一个参数中,存在一个特殊的属性<code>raw</code> ,我们可以通过它来访问模板字符串的原始字符串,而不经过特殊字符的替换。</p>
<pre><code class="language-javascript">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'</code></pre>
<p>另外,使用<a href="Reference/Global_Objects/String/raw" title="String.raw() 是一个模板字符串的标签函数,它的作用类似于 Python 中的字符串前缀 r 和 C# 中的字符串前缀 @,是用来获取一个模板字符串的原始字面量值的。"><code>String.raw()</code></a> 方法创建原始字符串和使用默认模板函数和字符串连接创建是一样的。</p>
<pre><code class="language-javascript"><code class="language-js"><span class="keyword token">var</span> str <span class="operator token">=</span> String<span class="punctuation token">.</span>raw<span class="template-string token"><span class="string token">`Hi\n</span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span><span class="number token">2</span><span class="operator token">+</span><span class="number token">3</span><span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">!`</span></span><span class="punctuation token">;</span>
<span class="comment token">// "Hi\n5!"</span>
str<span class="punctuation token">.</span>length<span class="punctuation token">;</span>
<span class="comment token">// 6</span>
str<span class="punctuation token">.</span><span class="function token">split</span><span class="punctuation token">(</span><span class="string token">''</span><span class="punctuation token">)</span><span class="punctuation token">.</span><span class="function token">join</span><span class="punctuation token">(</span><span class="string token">','</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">// "H,i,\,n,5,!"</span></code>
</code></pre>
<h3 id="带标签的模版字面量及转义序列">带标签的模版字面量及转义序列</h3>
<p>自ES2016起带标签的模版字面量遵守以下转义序列的规则</p>
<ul>
<li>Unicode字符以"\u"开头,例如<code>\u00A9</code></li>
<li>Unicode码位用"\u{}"表示,例如<code>\u{2F804}</code></li>
<li>十六进制以"\x"开头,例如<code>\xA9</code></li>
<li>八进制以"\"和数字开头,例如<code>\251</code></li>
</ul>
<p>这表示类似下面这种带标签的模版是有问题的因为对于每一个ECMAScript语法解析器都会去查找有效的转义序列但是只能得到这是一个形式错误的语法</p>
<pre><code class="language-javascript">latex`\unicode`
// 在较老的ECMAScript版本中报错ES2016及更早
// SyntaxError: malformed Unicode character escape sequence
</code></pre>
<h4 id="ES2018关于非法转义序列的修订">ES2018关于非法转义序列的修订</h4>
<p>带标签的模版字符串应该允许嵌套支持常见转义序列的语言(例如<a class="external" href="https://en.wikipedia.org/wiki/Domain-specific_language" rel="noopener">DSLs</a><a class="external" href="https://en.wikipedia.org/wiki/LaTeX" rel="noopener">LaTeX</a>。ECMAScript提议<a class="external" href="https://tc39.github.io/proposal-template-literal-revision/" rel="noopener">模版字面量修订</a>(第4阶段将要集成到ECMAScript 2018标准) 移除对ECMAScript在带标签的模版字符串中转义序列的语法限制。</p>
<p>不过,非法转义序列在"cooked"当中仍然会体现出来。它们将以 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a> 元素的形式存在于"cooked"之中:</p>
<pre><code class="language-javascript">function latex(str) {
return { "cooked": str[0], "raw": str.raw[0] }
}
latex`\unicode`
// { cooked: undefined, raw: "\\unicode" }</code></pre>
<p>值得注意的是,这一转义序列限制只对带标签的模板字面量移除,而不包括不带标签的模板字面量:</p>
<pre><code class="language-js example-bad">let bad = `bad escape sequence: \unicode`;</code></pre>
<h2 id="规范" style="font-size: 2.14285714285714rem;">规范</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><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-template-literals" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Template Literals</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition. Defined in several section of the specification: <a class="external" href="http://www.ecma-international.org/ecma-262/6.0/#sec-template-literals" rel="noopener">Template Literals</a>, <a class="external" href="http://www.ecma-international.org/ecma-262/6.0/#sec-tagged-templates" rel="noopener">Tagged Templates</a></td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-template-literals" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Template Literals</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td>Defined in several section of the specification: <a class="external" href="https://tc39.github.io/ecma262/#sec-template-literals" rel="noopener">Template Literals</a>, <a class="external" href="https://tc39.github.io/ecma262/#sec-tagged-templates" rel="noopener">Tagged Templates</a></td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/proposal-template-literal-revision/" rel="noopener">Template Literal Revision</a></td>
<td>Stage 4 draft</td>
<td>Drops escape sequence restriction from tagged templates</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容" style="font-size: 2.14285714285714rem;">浏览器兼容</h2>
<div>
<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><a class="new" href="Reference/Template_literals" rel="nofollow">Template literals</a></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
41</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
34</td><td class="bc-supports-no bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
28</td><td class="bc-supports-yes bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
9</td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
41</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
41</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
34</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
28</td><td class="bc-supports-unknown bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr title="Compatibility unknown; please update this.">
?
</abbr></td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4.0</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4.0.0</td></tr><tr><th scope="row">Escape sequences allowed in tagged template literals <div class="bc-icons"><abbr class="only-icon" title="Experimental. Expect behavior to change in the future."><span>Experimental</span><i class="ic-experimental"></i></abbr></div></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
62</td><td class="bc-supports-no bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
53</td><td class="bc-supports-no bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
49</td><td class="bc-supports-no bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
62</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
62</td><td class="bc-supports-no bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
53</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
49</td><td class="bc-supports-no bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-no bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-no bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td></tr></tbody></table><section class="bc-legend" id="sect1"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
 
</abbr></span></dt><dd>Full support</dd><dt><span class="bc-supports-no bc-supports">
<abbr class="bc-level bc-level-no only-icon" title="No support">
<span>No support</span>
 
</abbr></span></dt><dd>No support</dd><dt><span class="bc-supports-unknown bc-supports">
<abbr class="bc-level bc-level-unknown only-icon" title="Compatibility unknown">
<span>Compatibility unknown</span>
 
</abbr></span></dt><dd>Compatibility unknown</dd><dt><abbr class="only-icon" title="Experimental. Expect behavior to change in the future."><span>Experimental. Expect behavior to change in the future.</span><i class="ic-experimental"></i></abbr></dt><dd>Experimental. Expect behavior to change in the future.</dd></dl></section></div><p></p>
</div>
<h2 id="相关链接" style="font-size: 2.14285714285714rem;">相关链接</h2>
<ul>
<li><a href="Reference/String" title="此页面仍未被本地化, 期待您的翻译!"><code>String</code></a></li>
<li><a href="Reference/Global_Objects/String/raw" title="String.raw() 是一个模板字符串的标签函数,它的作用类似于 Python 中的字符串前缀 r 和 C# 中的字符串前缀 @,是用来获取一个模板字符串的原始字面量值的。"><code>String.raw()</code></a></li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar">Lexical grammar</a></li>
<li><a class="external" href="https://gist.github.com/WebReflection/8f227532143e63649804" rel="noopener">Template-like strings in ES3 compatible syntax</a></li>
<li><a class="external" href="https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2/" rel="noopener">"ES6 in Depth: Template strings" on hacks.mozilla.org</a></li>
</ul>
</article>