JavaScript: Template Literals

 20th August 2020 at 2:19pm

Template literals (aka. template strings) 是 ES2015 提出的语法特性,方便了字符串拼接。

基础:

`string text`

多行字符串:

`string text line 1
 string text line 2`

模板:

`string text ${expression} string text`

Tagged templates:

tag`string text ${expression} string text`

其中 tagged templates 是比较复杂的。它设计之初是希望 tag 函数可以拿到 template string 中的信息,比如它有几段字符串、有哪些表达式,从而可以做一些加工或者逻辑,再返回加工后的信息。这是 MDN 的一个例子:

let person = 'Mike';
let age = 28;

function myTag(strings, personExp, ageExp) {
  let str0 = strings[0]; // "That "
  let str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // let str2 = strings[2];

  let ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  // We can even return a string built using a template literal
  return `${str0}${personExp}${str1}${ageStr}`;
}

let output = myTag`That ${ person } is a ${ age }`;

console.log(output);
// That Mike is a youngster

另外一个例子,配合使用 Spread Operator

function tag(strings, ...values) {
  console.log(strings);
  console.log(values);
  
  return 'whatever';
}

let a = 1;
let b = 2;
tag`a = ${a}, b = ${b}`

// Output:
// ["a = ", ", b = ", ""]
// [1, 2]

注意 strings 中会带有最后的空字符串。一般没什么用处。strings 中还会有一个 raw 属性,返回未 escaped 的原字符串(比如 \n 这些)。

对于业界在 tagged template 上的实际使用,有 styled-components 中 大量使用 它来 扩展 API 能力

const mixin = css`...`

styled.div`
  /* this function would just be toString()'d */
  background: ${p => p.color || 'white'};

  /* this mixin wouldn't be flattened into the rest of the rules */
  ${mixin}
`

如果没有 tagged template,上面例子中的 arrow function 会简单地被转成 string,styled-component 的 API 将无法拿到函数对象;同时它也无法拿到 mixin 做更复杂的处理。