模板文字和无括号的函数调用

Template literals and parentheses-less function calls

我最近了解到 ES6 允许在使用模板文字作为参数时进行不带括号的函数调用。例如

showstring`Hello World`;

然而,在阅读了一些关于此功能的文章后,我对 JS 如何处理这些调用背后的逻辑知之甚少。

在对我的代码进行了一些排列后,我仍在努力拼凑出当以这种方式调用时模板文字在函数内部是如何分解的模式。

const showstring = (str) => {
  console.log(str);
}
showstring`Hello World`;

上面代码中发生的事情很简单,字符串文字作为数组接收,其中第一个也是唯一的元素是字符串。

一旦我开始在模板中使用表达式,就会让人感到困惑。例如

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring`Hello World ${name} ${name} ${1 + 2} and more`;

所以看起来 ...values 部分解构了所有表达式。但是,为什么 str 数组在这些位置有空字符串?

我只是没有完全理解它在这里遵循的模式。有人可以解释这个功能吗?或者给我推荐一篇好文章?

在第二个代码片段中,记录了这些:

// str
[
  "Hello World ",
  " ",
  " ",
  " and more"
]

// values
[
  "John",
  "John",
  3
]

如果您所说的“空字符串”是指 str 数组的第 2 项和第 3 项,则它们不是空字符串;它们是带有单个 space 的字符串。它们来自模板文字中表达式之间的 spaces:

showstring`Hello World ${name} ${name} ${1 + 2} and more`;
//                            ^       ^

当模板文字前面有表达式时——在本例中为 showstring——它被称为 tagged template.

在您的 showstring 函数中,str 总是比 values 数组多一项。例如。看看这些日志是什么:

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring``;
showstring`${name}`;
showstring`Hello ${name}!`;

这不是您的职能所特有的;这就是标记模板的工作方式。来自 Tagged templates section in the book JavaScript for impatient programmers (ES2020 edition):

The function before the first backtick is called a tag function. Its arguments are:

  • Template strings (first argument): an Array with the text fragments surrounding the interpolations ${}.
  • Substitutions (remaining arguments): the interpolated values.

关于您的评论:

Interestingly though, that single space will always remain a single space no matter how many spaces you put between the expressions when calling the function. Any idea why it trims to just one space?

好像不是这样的。这将记录一个包含三个 spaces:

的字符串

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring`Hello ${name}   ${name}!`;

您是否可能将结果打印到 DOM?除非您使用 <pre>white-space: pre; 或类似的东西,否则多个 space 只显示为一个,因此看起来结果似乎被修剪为只有一个 space。