65.9K
CodeProject 正在变化。 阅读更多。
Home

ES6 即将到来:模板字符串

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (2投票s)

2015 年 10 月 2 日

CPOL

6分钟阅读

viewsIcon

7925

模板字符串是 ES6 中一个巧妙的小胜利,现在就可以使用。

ES6 是 JavaScript 的未来,它已经到来。它是一个已完成的规范,它带来了许多语言所需的功能,以保持与当前网络需求的竞争力。并非 ES6 中的所有内容都适合您,在这个系列的小文章中,我将展示非常方便且已经可用的功能。

如果您查看我编写的 JavaScript 代码,您会发现我总是使用单引号来定义字符串,而不是双引号。JavaScript 对两者都无所谓,以下两个示例做的事情完全相同

var animal = "cow";
var animal = 'cow';

我更喜欢单引号的原因是,首先,这样更容易组装带有正确引用属性的 HTML 字符串

// with single quotes, there's no need to 
// escape the quotes around the class value
var but = '<button class="big">Save</button>';

// this is a syntax error:
var but = "<button class="big">Save</button>";

// this works:
var but = "<button class=\"big\">Save</button>";

现在您唯一需要转义的情况是您在 HTML 中使用单引号,这应该是非常罕见的。我能想到的唯一情况是内联 JavaScript 或 CSS,这意味着您很可能正在对您的标记做一些可疑或绝望的事情。即使在您的文本中,您也最好不要使用单引号,而是使用排版上更令人愉悦的 ‘。

旁注:当然,HTML 足够宽容,可以省略引号或在属性周围使用单引号,但我更喜欢为人类创建可读的标记,而不是依赖解析器的宽恕。我们之所以让 HTML5 解析器宽容,是因为人们过去编写了糟糕的标记,而不是以此为借口继续这样做。

在 DHTML 时代,我受够了 document.write 在新的弹出窗口中在 frameset 中创建文档以及其他糟糕的实践,以至于我再也不想使用转义字符了。有时,我们需要使用三次,而那甚至在我们编辑代码时还没有颜色高亮。那真是一团糟。

字符串中的表达式替换?

我喜欢单引号的另一个原因是,我曾经为许多大型网站编写过大量 PHP 代码,性能在那里非常重要。在 PHP 中,单引号和双引号之间存在差异。单引号字符串中没有任何替换,双引号字符串则有。这意味着在 PHP 3 和 4 时代,使用单引号要快得多,因为解析器不必遍历字符串来替换值。这是一个示例,说明这意味着什么

<?php
  $animal = 'cow';
  $sound = 'moo';
 
  echo 'The animal is $animal and its sound is $sound';
  // => The animal is $animal and its sound is $sound
 
  echo "The animal is $animal and its sound is $sound";
  // => The animal is cow and its sound is moo
?>

JavaScript 没有这种替换功能,这就是为什么我们不得不连接字符串才能达到相同的效果。这非常笨拙,因为您需要一直跳进跳出引号。

var animal = 'cow';
var sound = 'moo';

alert('The animal is ' + animal + ' and its sound is ' +
 sound);
// => "The animal is cow and its sound is moo"

多行混乱

这在更长更复杂的字符串中会变得非常混乱,尤其是在我们组装大量 HTML 时。而且,您很可能迟早会遇到您的 linting 工具抱怨行尾的 + 之后有尾随空格。这是基于 JavaScript 没有多行字符串的问题

// this doesn't work
var list = '<ul>
  <li>Buy Milk</li>
  <li>Be kind to Pandas</li>
  <li>Forget about Dre</li>
</ul>';
 
// This does, but urgh… 
var list = '<ul>\
  <li>Buy Milk</li>\
  <li>Be kind to Pandas</li>\
  <li>Forget about Dre</li>\
</ul>';
 
// This is the most common way, and urgh, too…
var list = '<ul>' +
'  <li>Buy Milk</li>' +
'  <li>Be kind to Pandas</li>' +
'  <li>Forget about Dre</li>' +
'</ul>';

客户端模板解决方案

为了解决 JavaScript 中字符串处理和连接的混乱问题,我们做了我们常做的事情——我们编写了一个库。有许多 HTML 模板库,其中 Mustache.js 可能是开创性的一个。所有这些都遵循自己的——非标准化的——语法,并在这种思维框架下工作。这有点像说您用 markdown 编写内容,然后才意识到“markdown”意味着许多不同的想法。

进入模板字符串

随着 ES6 及其标准化的到来,我们现在可以欢欣鼓舞,因为 JavaScript 在处理字符串方面有了一个新成员:模板字符串当前浏览器对模板字符串的支持令人鼓舞:Chrome 44+、Firefox 38+、Microsoft Edge 和 Webkit 都已支持。遗憾的是,Safari 尚未支持,但它会很快跟上。

模板字符串的巧妙之处在于它使用了一种新的字符串分隔符,该分隔符在 HTML 和普通文本中都没有使用:反引号 (`)。

使用这个,我们现在在 JavaScript 中有了字符串表达式替换

var animal = 'cow';
var sound = 'moo';
 
alert(`The animal is ${animal} and its sound is ${sound}`);
// => "The animal is cow and its sound is moo"

${} 结构可以接受任何返回值的 JavaScript 表达式,例如您可以进行计算或访问对象的属性

var out = `ten times two totally is ${ 10 * 2 }`;
// => "ten times two totally is 20"
 
var animal = {
  name: 'cow',
  ilk: 'bovine',
  front: 'moo',
  back: 'milk',
}
alert(`
  The ${animal.name} is of the 
  ${animal.ilk} ilk, 
  one end is for the ${animal.front}, 
  the other for the ${animal.back}
`);
// => 
/*
  The cow is of the 
  bovine ilk, 
  one end is for the moo, 
  the other for the milk
*/

最后一个例子也向您展示了多行字符串不再是问题。

标记模板

模板字符串的另一个功能是可以在其前面加上一个标签,这是一个函数的名称,该函数被调用并将字符串作为参数。例如,您可以对结果字符串进行 URL 编码,而无需一直诉诸于可怕的 namedencodeURIComponent

function urlify (str) {
  return encodeURIComponent(str);
}
 
urlify `http://beedogs.com`;
// => "http%3A%2F%2Fbeedogs.com"
urlify `woah$£$%£^$"`;
// => "woah%24%C2%A3%24%25%C2%A3%5E%24%22"
 
// nesting also works:
 
var str = `foo ${urlify `&&`} bar`;
// => "foo %26%26 bar"

这可行,但依赖于隐式数组到字符串的强制转换。传递给函数的参数不是字符串,而是字符串和值的数组。如果以我在此处显示的方式使用,为了方便起见,它将转换为字符串,但正确的方法是直接访问数组成员。

从模板字符串中检索字符串和值

在标签函数内部,您不仅可以获取完整的字符串,还可以获取其部分。

function tag (strings, values) {
  console.log(strings);
  console.log(values);
  console.log(strings[1]);
}
tag `you ${3+4} it`;
/* =>
 
Array [ "you ", " it" ]
7
it
 
*/

还为您提供了一个原始字符串数组,这意味着您将获得字符串中的所有字符,包括控制字符。例如,假设您使用 \n 添加了一个换行符。您将在字符串中获得双空格,但在原始字符串中获得 \n 字符

function tag (strings, values) {
  console.log(strings);
  console.log(values);
  console.log(strings[1]);
  console.log(string.raw[1]);
}
 
tag `you ${3+4} \nit`;
/* =>
 
Array [ "you ", "  it" ]
7
 
it
 \nit
*/

结论

模板字符串是 ES6 中那些巧妙的小胜利之一,现在就可以使用。如果您必须支持旧版浏览器,您当然可以将您的 ES6 转译为 ES5;您可以使用像 featuretests.io 这样的库或使用以下代码进行模板字符串支持的功能测试

var templatestrings = false;
try {
  new Function( "`{2+2}`" );
  templatestrings = true;
} catch (err) {
  templatestrings = false;
} 
 
if (templatestrings) {
	// …
}

更多关于模板字符串的文章

更多关于 JavaScript 的实践

本文是 Microsoft 技术推广人员关于实际 JavaScript 学习、开源项目和互操作性最佳实践的 Web 开发系列文章的一部分,其中包括 Microsoft Edge 浏览器和新的 EdgeHTML 渲染引擎

我们鼓励您使用 dev.modern.IE 上的免费工具,在包括 Microsoft Edge(Windows 10 的默认浏览器)在内的各种浏览器和设备上进行测试。

来自我们工程师和布道者的 Microsoft Edge 和 Web 平台深度技术学习

更多免费的跨平台工具和网络平台资源

© . All rights reserved.