ES8 模板标签函数 Tagged Templates 详细介绍

在 JavaScript 中,模板字符串的出现让字符串的拼接更加方便和直观。但是如果对模板字符串进行更加复杂的操作时,我们就需要使用 ES8 中提供的模板标签函数 Tagged Templates。

什么是模板标签函数 Tagged Templates

在 JavaScript 中,有一种奇特的语法函数名 + 模板字符串,其中的函数被称为模板标签函数(Tag Function)。这种语法是用于实现 Tagged Templates,其作用是将模板字符串与 JavaScript 表达式一起使用。

使用模板标签函数的方式示例:

function tagFunc(strings, ...values) {
  console.log(strings); // ['hello', ', my name is ', '']
  console.log(values); // ['world', 'JavaScript']
}

let name = 'world';
let lang = 'JavaScript';
tagFunc`hello, my name is ${name} and I'm learning ${lang}`;

在上面的例子中,tagFunc 是模板标签函数,后面的模板字符串中包含两个表达式(${name}${lang}),其中 ${name}${lang} 就是模板字符串中的 JavaScript 表达式。当模板标签函数被调用时,它会以字符串数组和表达式参数的方式接收组合后的模板字符串,我们将其分别保存在参数 stringsvalues 中。

实际应用场景

模板标签函数经常用于涉及到模板字符串的高级业务逻辑中,比如拼接多个模板字符串、处理与模板字符串相关的语言、实现模板字符串的缓存等等。

实现模板字符串的高亮

我们可以使用模板标签函数来实现模板字符串的高亮,示例代码如下:

function highlight(strings, ...values) {
  let str = '';
  strings.forEach((string, i) => {
    str += string + (values[i] || '');
  });
  return str.replace(/\$\{(?:[^\\`]|\\\`|\\\\|\\\$)*\}/g, '<mark>$&</mark>');
}

let code = `function hello(name, age) {
  return \`Hello \${name}, you are \${age} years old.\`;
}`;

document.getElementById('demo').innerHTML = highlight`${code}`;

在上面的示例代码中,我们使用 highlight 函数将代码中的占位字符 ${} 包裹起来,实现了代码的高亮效果。本例中的正则表达式是专门针对 ${} 的语法而编写的。

快速缓存计算结果

采用 Tagged Templates 模式可以实现缓存计算结果的功能,示例代码如下:

function memoize(func) {
  let cache = new Map();

  let executor = function (strings, ...values) {
    let key = strings + JSON.stringify(values);
    if (cache.has(key)) {
      console.log('Cache hit');
      return cache.get(key);
    } else {
      console.log('Cache miss');
      let result = func(strings, ...values);
      cache.set(key, result);
      return result;
    }
  };

  executor.cache = cache;

  return executor;
}

let add = memoize(function (strings, ...values) {
  let sum = 0;
  values.forEach((x) => (sum += Number(x)));
  return `${strings[0]}${sum}`;
});

console.log(add`The total is ${1 + 2 + 3}`); // Cache miss, The total is 6
console.log(add`The total is ${1 + 2 + 3}`); // Cache hit, The total is 6
console.log(add.cache); // Map { 'The total is 123,[1,2,3]' => 'The total is 6' }

在上面的示例中,我们定义了一个 memoize 函数,它接收一个函数作为参数,返回一个新的函数,在这个函数内部实现了对结果的缓存,从而实现了缓存计算结果的功能。

模板标签函数的参数

模板标签函数 tagFunc 接收到的参数包括两种类型:stringsvalues

strings

strings 是一个字符串数组,它包含了模板字符串的字面值部分,也就是字符串中没有被表达式替换的部分。在 strings 数组中,相邻的两个字符串被表达式分隔开。第一个字符串放在数组中的第一个位置,最后一个字符串放在数组中的最后一个位置。

values

values 数组中包含了所有表达式的值,与 strings 中的字符串一一对应。每个表达式变量都会转换成一个 values 中的参数,然后通过 ${} 的位置占位符与 strings 中对应的字符串组合成最终的字符串。

总结

Tagged Templates 可以让我们在 JavaScript 中更方便地处理模板字符串,达到更加底层的定制和控制效果。模板标签函数是 JavaScript 中比较高级的函数用法,可以应用于许多实际业务场景。在实际项目中,我们需要对模板标签函数有更加深入的了解和应用,以便更加高效地完成开发工作。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65928c05eb4cecbf2d74fc65


纠错反馈