字符串模板 之 标签模板

475 阅读3分钟

这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

前言

ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。一般情况,泛指, 5.1版以后的标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等

我们一起来学习:

  • 标签模板

标签模板格式

和普通的字符串模板不一样,其在前面添加一个函数,我们称其为标签函数,最后返回的是通过标签函数处理过后的东西。

先看看标签函数的参数:

function tagAge(strings, exp1, exp2, .....)

  • strings
    字符串值的数组. 被模板字符串表达式分割的字符串数组。
  • exp1, exp2, .....
    模板字符串表达式的值

我们先看一个简单的例子:

function tag(strings, name, age){
    console.log(strings);
    console.log(name, age);
}

const name = 'tom';
const age = 18;

console.log(tag`i am ${name}, my age is ${18}`)
// (3) ['i am ', ', my age is ', '', raw: Array(3)]
// tom 18
// undefined  因为tag没有任何返回值,所以默认是undefined

这个例子的

  • strings: ['i am ', ', my age is ', '', raw: Array(3)]
  • name: tom
  • age: 18 来个图,更好理解:

image.png

我们tag没有返回任何值,我们可以任意定义值:

function tag(strings, name, age){
    return name + " is " + ( age > 60 ? "old""young") 
}

const name = 'tom';
const age = 18;

console.log(tag`i am ${name}, my age is ${18}`)
// tom is young

是不是非常有意思。

标签函数第一个参数的raw属性

标签函数的第一个参数strings,有一个raw属性,也是一个数组。

该数组的成员与strings数组完全一致。

唯一的区别,就是字符串里面的斜杠都被转义了

我们一起看看例子:


function tag(strings){
    console.log("strings:", strings);
    console.log("strings.raw:", strings.raw);
}

console.log(tag`测试\r\t\n的数据`);
// strings: ['测试\r\t\n的数据', raw: Array(1)]
// strings.raw: ['测试\\r\\t\\n的数据']

如何返回原值

当然这样做可能你觉得无聊,其实不然。 我们可以用标签函数做逻辑处理,如果没有需要额外处理,返回原值也是理所当然。

我们这里要清楚一点,strings的长度肯定是要比如后面表达式的参数值多1,这个很好理解,毕竟是以表达式作为分隔的。

结合ES6的剩余参数,或者 ES5的 arguments参数。

ES6

ES6嘛,剩余参数 + 可以使用for循环,我嘛,就使用map吧!

function tagOri(strings, ...expValues) {
  const arr = expValues.map((_, index)=> {
      return strings[index] + expValues[index]
  });
  
  return arr.concat(expValues.length).join("")
}

const name = 'tom';
const age = 18;

console.log(tagOri`i am ${name}, my age is ${18}`)
// i am tom, my age is 182

ES5

没有剩余参数,就使用arguments的特性吧。

function tagOri(strings) {
  const expValues = [].slice.call(arguments, 1)

  const arr = expValues.map((_, index)=> {
      return strings[index] + expValues[index]
  });
  
  return arr.concat(expValues.length).join("")
}

const name = 'tom';
const age = 18;

console.log(tagOri`i am ${name}, my age is ${18}`)
// i am tom, my age is 182

用途

因为其可以对输入进行判断,然后加工处理。 我工作种还没实际这么使用过, 阮大神提到 过滤 HTML 字符串,防止用户输入恶意内容。

let message =
  SaferHTML`<p>${sender} has sent you a message.</p>`;

function SaferHTML(templateData) {
  let s = templateData[0];
  for (let i = 1; i < arguments.length; i++) {
    let arg = String(arguments[i]);

    // Escape special characters in the substitution.
    s += arg.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}

小结

今天你收获了吗?

引用

字符串的扩展
模板字符串