# 六、模板字面值

`Template`文字通过在倒勾字符中包含字符串来表示，并为构建单行和多行字符串提供语法糖。这类似于 Perl、Python 等语言中的字符串插值特性。可选地，可以添加一个标签来允许定制字符串构造，避免注入攻击或从字符串内容构造更高级别的数据结构。

以下是模板文字的一些示例:

代码清单 89

```js
  `In JavaScript '\n' is a line-feed.`
  `Now I can do multi-lines
   with template literals.` 

```

通过字符串插值，我们现在可以以简洁明了的方式编写非常强大的字符串。考虑以下示例:

代码清单 90

```js
  var customer = { name: "Matt" };
  var product = { name: "Halo 5: Guardians" };
  let gift = { timelimit:
  '4 hours', amount:
  50.00 };
  let message = `Dear
  ${customer.name},\n
  Thank you for making a recent purchase
  of '${product.name}' on Amazon.com.
  We would love to get your feedback on
  your experience.
  If you respond in the next
  ${gift.timelimit}, we will give you a gift
  certificate of $${gift.amount} dollars!

  We look forward to hearing from you!

  Best Regards,

  Amazon Customer Relations`;
  console.log(message);

```

运行前面的代码会产生以下输出:

代码清单 91

```js
  Dear Matt,

  Thank you for making a recent purchase of 'Halo 5:
  Guardians' on Amazon.com.
  We would love to get your feedback on your
  experience.
  If you respond in the next 4 hours, we will give you
  a gift
  certificate of $50 dollars!

  We look forward to hearing from you!

  Best Regards,

  Amazon Customer Relations

```

这真不错！我可以看到很多很酷的字符串插值，不再局限于旧的字符串连接方法。

让我们看看我们还能做什么。考虑以下示例:

代码清单 92

```js
  let getTotal = (qty, amount) =>
  {
    return
  qty * amount;
  };
  let message = `Shopping
  cart total: $${getTotal(2, 2.99)}`;
  console.log(message);

```

运行前面的代码会产生以下输出:

代码清单 93

```js
  Shopping cart total: $5.98 

```

如您所见，我们可以在字符串插值中调用函数。

您甚至可以在字符串插值表达式中执行操作，如下所示:

代码清单 94

```js
  let message = `Shopping
  cart total: $${2
  * 2.99}`;

  console.log(message);

```

运行前面的代码会产生以下输出:

代码清单 95

```js
  Shopping cart total: $5.98 

```

也许你想构建一个动态的网址？这很容易做到。考虑以下示例:

代码清单 96

```js
  let credentials = "private-user=admin&private-pw=p@$$w0rd";
  let a = "one";
  let b = "two";
  let url = `http://myapp.com/login?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
  `;
  console.log(url);
  let post = `POST
  ${url}`;

```

如您所见，我们可以在很多不同的场景中使用这个新功能。

也许有一天你希望可以动态地创建一个模板文字，也许是基于一个数据库调用或一些其他的过程。这需要更多的工作，但是你可以通过一点小技巧来支持动态模板。考虑以下示例:

代码清单 97

```js
  let processMarkup
  = (markup, data) =>
  {
    let
  fields = markup.match(/{(.+?)}/g);
    let
  args = [];
    let
  params = [];
    fields.forEach((field,index,list) => {
      field =
  field.replace(/{/g, '');
      field =
  field.replace(/}/g, '');
      args.push(data[field]);
      params.push(field);
    });
    let
  template = markup.replace(/{/g, '${');
    let
  fn = assemble(template, params);
    let
  render = fn.apply(null, args);
    return
  render;
  }
  let assemble = (template, params) =>
  {
    return
  new Function(params,
  "return `" + template +"`;");
  }
  let markup = `Hello
  {fname} {lname}, how are you?`;
  let data = { fname: "Matthew", lname: "Duffield"
  };
  let template = processMarkup(markup, data);
  console.log(template);

```

以下是运行上述代码的输出:

代码清单 98

```js
  Hello Matthew Duffield, how are you? 

```

这可能不是最推荐的做法，但它确实向您展示了您可以创建动态模板。请注意，我们不能使用与字符串插值中使用的符号相同的符号，因为那样会立即得到解决。这就是`Function()`构造函数的作用，它允许我们用新的参数“组装”我们的模板。同样，这是一种制作动态模板的幼稚方法，但是如果您需要动态生成模板，它确实提供了很大的力量。

正如您所看到的，我们可以通过许多不同的方式使用这个新功能。