为什么模板字符串(``)将前面的标记作为函数执行?

Why do template strings (``) execute preceding token as a function?

我今天遇到了一个错误 - TypeError: "fa" is not a function - 经过短暂的调查,我找到了原因。我忘记了对象字面量中的逗号,这让我得到了一个字符串,后跟一个模板字符串,本质上是这样的:"fa"``。看过之后 not a function 我希望找到一些令人反感的括号并发现这很好奇,所以我加深了对 Node REPL 的调查。

''``               // TypeError: '' is not a function
'foo'``            // TypeError: 'foo' is not a function
1``                // TypeError: 1 is not a function
(() => 'foobar')`` //'foobar'

好的,所以我发现模板字符串的工作方式似乎类似于在标记后放置括号。越来越好奇了。

我想知道它是否传递任何参数,所以我写了这个:

function showArgs () {
  return arguments
}

showArgs()                  // {}
showArgs``                  // { '0': [ '' ] }
showArgs`foo`               // { '0': [ 'foo' ] }
showArgs`foo${'bar'}`       // { '0': [ 'foo', '' ], '1': 'bar' }
showArgs`foo${'bar'}`   // { '0': [ 'foo', '', '' ], '1': 'bar', '2': 1 }
showArgs(`foo${'bar'}`) // { '0': 'foobar1`' }

这是怎么回事?

参数显然与模板字符串有关,因为它们可用于通过将第 n 数组项与 n 连接起来来构造它+ 第 1 个参数并将它们全部连接起来,但为什么模板字符串使用这些参数执行前面的标记?

查看tagged template literals.

A more advanced form of template literals are tagged template literals. With them you are able to modify the output of template literals using a function. The first argument contains an array of string literals [...]. The second, and each argument after the first one, are the values of the processed (or sometimes called cooked) substitution expressions [...]. In the end, your function returns your manipulated string.


来自 MDN 的示例:

var a = 5;
var b = 10;

function tag(strings, ...values) {
  console.log(strings[0]); // "Hello "
  console.log(strings[1]); // " world "
  console.log(strings[2]); // ""
  console.log(values[0]);  // 15
  console.log(values[1]);  // 50

  return "Bazinga!";
}

tag`Hello ${ a + b } world ${ a * b }`;
// "Bazinga!"