了解JavaScript中的模板文字

来自菜鸟教程
跳转至:导航、​搜索

作者选择了 COVID-19 Relief Fund 作为 Write for DOnations 计划的一部分来接受捐赠。

介绍

ECMAScript 规范 (ES6) 2015 版向 JavaScript 语言添加了 模板文字。 模板文字是在 JavaScript 中创建 字符串的一种新形式,它增加了许多强大的新功能,例如更轻松地创建多行字符串以及使用占位符将表达式嵌入字符串中。 此外,称为 标记模板文字 的高级功能允许您对字符串中的表达式执行操作。 所有这些功能都增加了作为开发人员的字符串操作选项,让您生成可用于 URLs 或自定义 HTML 元素 的函数的动态字符串。

在本文中,您将了解单引号/双引号字符串和模板文字之间的区别,贯穿声明不同形状字符串的各种方式,包括多行字符串和根据变量值变化的动态字符串或表达。 然后,您将了解标记模板并查看使用它们的项目的一些真实示例。

声明字符串

本节将回顾如何使用单引号和双引号声明字符串,然后向您展示如何对模板文字执行相同操作。

在 JavaScript 中,可以用单引号 (' ') 编写字符串:

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

字符串也可以用双引号 (" ") 编写:

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

JavaScript 中单引号或双引号字符串之间没有重大区别,不像其他语言可能允许 interpolation 在一种类型的字符串中但不允许在另一种类型的字符串中。 在这种情况下,插值是指将占位符评估为字符串的动态部分。

单引号或双引号字符串的使用主要归结为个人喜好和约定,但结合使用,每种类型的字符串只需要 escape 自己的引号类型:

// Escaping a single quote in a single-quoted string
const single = '"We don\'t make mistakes. We just have happy accidents." - Bob Ross'

// Escaping a double quote in a double-quoted string
const double = "\"We don't make mistakes. We just have happy accidents.\" - Bob Ross"

console.log(single);
console.log(double);

此处 log() 方法的结果将相同的两个字符串打印到 控制台

Output"We don't make mistakes. We just have happy accidents." - Bob Ross
"We don't make mistakes. We just have happy accidents." - Bob Ross

另一方面,模板文字是通过用反引号字符或重音符号 (`) 包围字符串来编写的:

const template = `Find freedom on this canvas.`

他们不需要转义单引号或双引号:

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

但是,他们仍然需要避开反引号:

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

模板文字可以做常规字符串可以做的所有事情,因此您可以用它们替换项目中的所有字符串并具有相同的功能。 但是,代码库中最常见的约定是仅在使用模板文字的附加功能时才使用模板文字,并且对所有其他简单字符串始终使用单引号或双引号。 如果由其他开发人员检查,遵循此标准将使您的代码更易于阅读。

现在您已经了解了如何使用单引号、双引号和反引号声明字符串,您可以继续了解模板文字的第一个优点:编写多行字符串。

多行字符串

在本节中,您将首先了解在 ES6 之前声明多行字符串的方式,然后了解模板文字如何使这更容易。

最初,如果您想在文本编辑器中编写一个跨越多行的字符串,您将使用 连接运算符 。 然而,这并不总是一个直截了当的过程。 以下字符串连接似乎跨越了多行:

const address = 
  'Homer J. Simpson' + 
  '742 Evergreen Terrace' + 
  'Springfield'

这可能允许您将字符串分成更小的行并将其包含在文本编辑器中的多行中,但它对字符串的输出没有影响。 在这种情况下,字符串都将在一行上,并且不会用换行符或空格分隔。 如果您将 address 记录到控制台,您将获得以下信息:

OutputHomer J. Simpson742 Evergreen TerraceSpringfield

您可以使用反斜杠字符 (\) 将字符串延续到多行:

const address =
  'Homer J. Simpson\
  742 Evergreen Terrace\
  Springfield'

这会将任何缩进保留为空格,但字符串仍将位于输出中的一行:

OutputHomer J. Simpson  742 Evergreen Terrace  Springfield

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

const address = 
  'Homer J. Simpson\n' + 
  '742 Evergreen Terrace\n' + 
  'Springfield'

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

OutputHomer J. Simpson
742 Evergreen Terrace
Springfield

然而,使用换行符来指定多行字符串可能是违反直觉的。 相比之下,使用模板文字创建多行字符串可能更直接。 无需连接、使用换行符或使用反斜杠。 默认情况下,只需按 ENTER 并将字符串写入多行即可:

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

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

OutputHomer J. Simpson
742 Evergreen Terrace
Springfield

任何缩进都将被保留,因此如果不希望缩进字符串中的任何其他行,这一点很重要。 例如,考虑以下情况:

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

虽然这种写法可能会使代码更易于阅读,但输出不会是:

OutputHomer J. Simpson
                 742 Evergreen Terrace
                 Springfield

现在涵盖了多行字符串,下一节将讨论如何使用不同的字符串声明将表达式插入到它们的值中。

表达式插值

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

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

当登录到控制台时,这将产生以下内容:

OutputThis string is using concatenation.

使用模板文字,表达式可以嵌入到 占位符 中。 占位符由 ${} 表示,大括号内的任何内容都被视为 JavaScript,而括号外的任何内容都被视为字符串:

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

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

OutputThis string is using interpolation.

在字符串中嵌入值的一个常见示例可能是创建动态 URL。 使用串联,这可能很麻烦。 例如,下面声明一个函数来生成一个OAuth访问字符串:

function createOAuthString(host, clientId, scope) {
  return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=' + scope
}

createOAuthString('https://github.com', 'abc123', 'repo,user')

记录此函数将在控制台生成以下 URL:

Outputhttps://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

使用字符串插值,您不再需要跟踪打开和关闭字符串以及连接运算符的位置。 这是使用模板文字的相同示例:

function createOAuthString(host, clientId, scope) {
  return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
}

createOAuthString('https://github.com', 'abc123', 'repo,user')

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

Outputhttps://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

您还可以在模板文字上使用 trim() 方法 来删除字符串开头或结尾的任何空格。 例如,以下使用箭头函数创建一个 HTML[1]

元素

带有自定义链接:

const menuItem = (url, link) =>
  `
<li>
  <a href="${url}">${link}</a>
</li>
`.trim()

menuItem('https://google.com', 'Google')

结果将被修剪掉所有的空白,确保元素被正确渲染:

Output<li>
  <a href="https://google.com">Google</a>
</li>

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

const sum = (x, y) => x + y
const x = 5
const y = 100
const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`

console.log(string)

此代码定义了 sum 函数和变量 xy,然后在字符串中同时使用函数和变量。 记录的结果将显示以下内容:

OutputThe sum of 5 and 100 is 105.

这对于 三元运算符 特别有用,它允许在字符串中使用条件:

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

此处记录的消息将根据 age 的值是大于还是小于 21 而改变。 由于在此示例中为 19,因此将记录以下输出:

OutputYou can not view this page

现在您已经了解了模板文字在用于插入表达式时如何有用。 下一节将通过检查标记模板文字以处理传递给占位符的表达式来更进一步。

标记的模板文字

模板字面量的一个高级特性是使用 标记的模板字面量 ,有时称为 模板标签 。 标记模板以解析模板文字的 标记函数 开头,允许您更好地控制操作和返回动态字符串。

在此示例中,您将创建一个 tag 函数以用作对标记模板进行操作的函数。 字符串字面量是函数的第一个参数,在此命名为 strings,插入到字符串中的任何表达式都使用 rest parameters 打包到第二个参数中。 您可以控制参数以查看它们将包含的内容:

function tag(strings, ...expressions) {
  console.log(strings)
  console.log(expressions)
}

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

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

由于您正在控制台记录 stringsexpressions,这将是输出:

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

第一个参数 strings 是一个 array 包含所有字符串文字:

  • "This is a string with "
  • " and "
  • " and "
  • " interpolated inside."

strings.raw 的这个参数上还有一个可用的 raw 属性,它包含没有处理任何转义序列的字符串。 例如,/n 将只是字符 /n 而不会转义为换行符。

第二个参数 ...expressions 是一个由所有表达式组成的剩余参数数组:

  • true
  • false
  • 100

字符串文字和表达式作为参数传递给标记模板函数 tag。 注意带标签的模板不需要返回字符串; 它可以对这些值进行操作并返回任何类型的值。 例如,我们可以让函数忽略所有内容并返回 null,如下 returnsNull 函数:

function returnsNull(strings, ...expressions) {
  return null
}

const string = returnsNull`Does this work?`
console.log(string)

记录 string 变量将返回:

Outputnull

可以在标记模板中执行的操作示例是对每个表达式的两侧应用一些更改,例如,如果您想将每个表达式包装在 HTML 标记中。 创建一个 bold 函数,将 <strong></strong> 添加到每个表达式:

function bold(strings, ...expressions) {
  let finalString = ''

  // Loop through all expressions
  expressions.forEach((value, i) => {
    finalString += `${strings[i]}<strong>${value}</strong>`
  })

  // Add the last string literal
  finalString += strings[strings.length - 1]

  return finalString
}

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

console.log(string)

此代码使用 forEach 方法 循环 expressions 数组并添加粗体元素:

OutputThis is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.

在流行的 JavaScript 库中有一些标记模板文字的示例。 graphql-tag 库使用 gql 标记模板将 GraphQL 查询字符串解析为 GraphQL 可以理解的抽象语法树 (AST):

import gql from 'graphql-tag'

// A query to retrieve the first and last name from user 5
const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`

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

import styled from 'styled-components'

const Button = styled.button`
  color: magenta;
`

// <Button> can now be used as a custom component

您还可以在标记的模板文字上使用内置的 String.raw 方法来防止处理任何转义序列:

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

这将记录以下内容:

OutputI want to write /n without it being escaped.

结论

在本文中,您回顾了单引号和双引号字符串文字,并了解了模板文字和标记模板文字。 模板文字通过在字符串中插入表达式并创建多行字符串而无需任何连接或转义,使许多常见的字符串任务变得更简单。 模板标签也是模板文字的一个有用的高级功能,许多流行的库都使用过,例如 GraphQL 和 styled-components

要了解有关 JavaScript 中字符串的更多信息,请阅读 如何在 JavaScript 中使用字符串如何在 JavaScript 中索引、拆分和操作字符串