了解 JavaScript 中的模板字面意义

作者选择了 COVID-19 救援基金作为 Write for Donations计划的一部分接受捐款。

介绍

2015 版 ECMAScript 规范 (ES6)template literals 添加到 JavaScript 语言中。 模板 literals 是创建 JavaScript 字符串的一种新形式,添加了许多强大的新功能,例如更容易创建多行字符串,并使用位置持有者在字符串中嵌入表达式。 此外,一个名为 tagged template literals 的先进功能允许您在字符串中执行表达式操作。 所有这些功能都增加了您作为开发人员的字符串操纵选项,允许您生成可用于 URL或功能定制 HTML 元素的动态字符串。

在本文中,您将探讨单/双引用字符串和模板字符串之间的差异,通过各种方式来声明不同形状的字符串,包括多行字符串和动态字符串,这些字符串取决于变量或表达式的值。

声明 Strings

本节将审查如何用单引文和双引文声明字符串,然后向您展示如何使用模板字符串做同样的事情。

在JavaScript中,一个字符串可以用单个引文(' ')写成:

1const single = 'Every day is a good day when you paint.'

一个字符串也可以用双引文(" ")写成:

1const double = "Be so very light. Be a gentle whisper."

在JavaScript中,单字符串或双字符串之间没有重大差异,与其他语言不同,它们可能允许在一种类型的字符串中进行 interpolation,而不是其他类型的字符串。

单字符串或双字符串的使用主要取决于个人偏好和惯例,但在连接中使用,每个字符串类型只需要(https://andsky.com/tech/tutorials/how-to-work-with-strings-in-javascript#escaping-quotes-and-apostrophes-in-strings)自己的引用类型:

1// Escaping a single quote in a single-quoted string
2const single = '"We don\'t make mistakes. We just have happy accidents." - Bob Ross'
3
4// Escaping a double quote in a double-quoted string
5const double = "\"We don't make mistakes. We just have happy accidents.\" - Bob Ross"
6
7console.log(single);
8console.log(double);

在这里log()方法的结果将打印相同的两个字符串到 控制台:

1[secondary_label Output]
2"We don't make mistakes. We just have happy accidents." - Bob Ross
3"We don't make mistakes. We just have happy accidents." - Bob Ross

相比之下,模板字母是通过围绕字符串的背面符号,或重大的口音(`)来写的:

1const template = `Find freedom on this canvas.`

他们不需要逃避单一或双重引用:

1const template = `"We don't make mistakes. We just have happy accidents." - Bob Ross`

然而,他们仍然需要逃避背杆:

1const template = `Template literals use the \` character.`

模板字符串可以做任何正常字符串可以做的事情,所以你可以用它们替换项目中的所有字符串,并具有相同的功能。然而,代码库中最常见的惯例是,在使用模板字符串的额外功能时,只使用模板字符串,并一致地使用所有其他简单字符串的单个或双重引用。

现在你已经看到了如何用单个引文、双引文和后台声明字符串,你可以转到模板字符串的第一个优势:写多行字符串。

多线链接

在本节中,您将首先通过 ES6 之前声明具有多个行的字符串的方式运行,然后看看模板字符串如何使这一点更容易。

起初,如果您想在文本编辑器中编写一个跨多个行的字符串,您会使用 concatenation operator

1const address = 
2  'Homer J. Simpson' + 
3  '742 Evergreen Terrace' + 
4  'Springfield'

这可能允许您将字符串分割成较小的行,并在文本编辑器中包含多个行,但不会影响字符串的输出。

1[secondary_label Output]
2Homer J. Simpson742 Evergreen TerraceSpringfield

您可以使用 backslash 字符(\)将字符串延续到多个行:

1const address =
2  'Homer J. Simpson\
3  742 Evergreen Terrace\
4  Springfield'

这将保留任何入口作为白空间,但字符串仍然在输出中的一个行:

1[secondary_label Output]
2Homer J. Simpson 742 Evergreen Terrace Springfield

使用新行字符(\n),您可以创建一个真正的多行字符串:

1const address = 
2  'Homer J. Simpson\n' + 
3  '742 Evergreen Terrace\n' + 
4  'Springfield'

当您登录到控制台时,将显示以下内容:

1[secondary_label Output]
2Homer J. Simpson
3742 Evergreen Terrace
4Springfield

然而,使用新行字符来指定多行字符串可能具有反直觉性。相反,创建具有模板字符串的多行字符串可以更简单。无需连接、使用新行字符或使用反行字符串。只需按ENTER并在多个行之间写字符串,默认情况下可以:

1const address = `Homer J. Simpson
2742 Evergreen Terrace
3Springfield`

将此记录到控制台的输出与输入相同:

1[secondary_label Output]
2Homer J. Simpson
3742 Evergreen Terrace
4Springfield

任何插头都将保留,因此如果不希望,在字符串中不要插头任何额外的行很重要。

1const address = `Homer J. Simpson
2                 742 Evergreen Terrace
3                 Springfield`

虽然这种写行方式可能会使代码更易于人读,但输出不会是:

1[secondary_label Output]
2Homer J. Simpson
3                 742 Evergreen Terrace
4                 Springfield

随着多行字符串现在被覆盖,下一节将处理如何将表达式与不同的字符串声明中介入其值。

表达式互动

在 ES6 之前的字符串中,用于创建一个具有变量或表达式的动态字符串:

1const method = 'concatenation'
2const dynamicString = 'This string is using ' + method + '.'

当您登录到控制台时,会产生如下:

1[secondary_label Output]
2This string is using concatenation.

在模板字母中,一个表达式可以嵌入到一个 placeholder. 一个位置保持者被表示为${},在曲折的支架内的一切被视为JavaScript,在支架外的一切被视为字符串:

1const method = 'interpolation'
2const dynamicString = `This string is using ${method}.`

dynamicString登录到控制台时,控制台将显示以下内容:

1[secondary_label Output]
2This string is using interpolation.

嵌入字符串中的一个常见例子可能是用于创建动态 URL。 通过连接,这可能很麻烦。 例如,以下说明一个 函数可以生成一个 OAuth访问字符串:

1function createOAuthString(host, clientId, scope) {
2  return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=' + scope
3}
4
5createOAuthString('https://github.com', 'abc123', 'repo,user')

登录此函数将为控制台提供以下URL:

1[secondary_label Output]
2https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

使用 string interpolation,您不再需要跟踪打开和关闭字符串和连接操作员的位置。

1function createOAuthString(host, clientId, scope) {
2  return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
3}
4
5createOAuthString('https://github.com', 'abc123', 'repo,user')

这将具有与 concatenation 示例相同的输出:

1[secondary_label Output]
2https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

您还可以使用模板上的 trim() 方法来删除字面上的字面空间,例如,下面的方法使用 箭头函数创建具有自定义链接的 HTML <li> 元素:

1const menuItem = (url, link) =>
2  `
3<li>
4  <a href="${url}">${link}</a>
5</li>
6`.trim()
7
8menuItem('https://google.com', 'Google')

结果将切除所有白色空间,确保元素的渲染正确:

1[secondary_label Output]
2<li>
3  <a href="https://google.com">Google</a>
4</li>

整个表达式可以被插入,而不仅仅是变量,如在这个示例中对两个数字的总和:

1const sum = (x, y) => x + y
2const x = 5
3const y = 100
4const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`
5
6console.log(string)

此代码定义了函数和变量xy,然后使用函数和变量在一个字符串中。

1[secondary_label Output]
2The sum of 5 and 100 is 105.

这在 外部运算符中尤其有用,它们允许在字符串中使用条件:

1const age = 19
2const message = `You can ${age < 21 ? 'not' : ''} view this page`
3console.log(message)

此处登录的消息将取决于年龄的值是否超过或低于21

1[secondary_label Output]
2You can not view this page

现在你有一个想法,模板字母可以用来调用表达式时是如何有用的。下一节将通过检查标记的模板字母来进一步研究这一点,以便与传递到位数的表达式一起工作。

寺庙文学

模板字母的先进功能是使用 _tagged 模板字母,有时称为 _template 标签。

在本示例中,您将创建一个标签函数来使用作为在标记模板上运行的函数。 字符串是该函数的第一个参数,在这里被称为字符串,并将任何插入字符串的表达式嵌入到第二个参数中,使用 残留参数

1function tag(strings, ...expressions) {
2  console.log(strings)
3  console.log(expressions)
4}

使用标签函数作为标记模板函数,并如下解析字符串:

1const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.`

由于您在控制台中记录字符串表达式,所以这将是输出:

1[secondary_label Output]
2(4) ["This is a string with ", " and ", " and ", " interpolated inside."
3(3) [true, false, 100]

第一个参数,‘字符串’,是一个包含所有字符串字母的 数组:

`这是一个具有``

  • ``插入的字符串。

在strings.raw上,这个参数还可以使用一个原始属性,其中包含字符串而无需处理任何逃避序列,例如, /n’ 只会是字符 /n’ 并且不会被逃入新行。

第二个参数,‘...表达式’,是由所有表达式组成的休息参数数组:

字符串和表达式作为参数传递到标记的模板函数标签。 请注意,标记的模板不需要返回一个字符串;它可以操作这些值并返回任何类型的值。

1function returnsNull(strings, ...expressions) {
2  return null
3}
4
5const string = returnsNull`Does this work?`
6console.log(string)

登录string变量将返回:

1[secondary_label Output]
2null

在标记模板中可以执行的操作的一个例子是将某些更改应用到每个表达式的两侧,例如要将每个表达式包装到 HTML 标签中。

 1function bold(strings, ...expressions) {
 2  let finalString = ''
 3
 4  // Loop through all expressions
 5  expressions.forEach((value, i) => {
 6    finalString += `${strings[i]}<strong>${value}</strong>`
 7  })
 8
 9  // Add the last string literal
10  finalString += strings[strings.length - 1]
11
12  return finalString
13}
14
15const string = bold`This is a string with ${true} and ${false} and ${100} interpolated inside.`
16
17console.log(string)

此代码使用 forEach 方法expressions 数组上循环并添加大胆元素:

1[secondary_label Output]
2This is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.

在流行的 JavaScript 库中,有几个标记模板字母的例子。 graphql-tag库使用标记为 gql 的模板来对 GraphQL 查询字符串进行解析,并将其列入 GraphQL 理解的抽象语法树(AST):

 1import gql from 'graphql-tag'
 2
 3// A query to retrieve the first and last name from user 5
 4const query = gql`
 5  {
 6    user(id: 5) {
 7      firstName
 8      lastName
 9    }
10  }
11`

另一个使用标记模板函数的库是 styled-components,它允许您从常规的 DOM元素中创建新的 React components并应用额外的 CSS 样式元素:

1import styled from 'styled-components'
2
3const Button = styled.button`
4  color: magenta;
5`
6
7// <Button> can now be used as a custom component

您还可以使用内置的 String.raw 方法在标记的模板字母上,以防止任何逃避序列被处理:

1const rawString = String.raw`I want to write /n without it being escaped.`
2console.log(rawString)

这将记录如下:

1[secondary_label Output]
2I want to write /n without it being escaped.

结论

在本文中,您审查了单和双引用字符串的字符串,并了解了模板字符串和标记的模板字符串。 模板字符串通过在字符串中插入表达式并创建多行字符串而简化许多常见的字符串任务,而无需任何连接或逃避。

有关 JavaScript 中的字符串的更多信息,请参阅 如何在 JavaScript 中使用字符串如何在 JavaScript 中索引、分割和操纵字符串

Published At
Categories with 技术
comments powered by Disqus