前端练习48 字体高亮函数

已经同步到个人博客,欢迎访问

知识点

标签模板

题目

完成highLight函数,可以把模板字符串中的插入内容替换掉,并且插入文档后显示红色,例如:

const yourName = 'ScriptOJ'
const myName = 'Jerry'
document.body.innerHTML = highlight`Hello, ${yourName}. I am ${myName}.`

CSS样式:

.red {
  color: red
}

实现

上面的关键是函数调用那一行:

highlight`Hello, ${yourName}. I am ${myName}.`

以我浅薄的学识,认为是题目出错了,哪有这样进行函数调用的,所以自作主张按照下面的调用方式实现:

highlight('Hello, ${yourName}. I am ${myName}.')

按照这种形式,以前联系过类似的问题,使用new Function可以实现替换模板字符串变量的功能:

const highlight = (str) => {
  let reg = /\$\{(.+?)\}/g;
  let match = reg.exec(str);
  let result = [];
  while(match) {
    result.push(match[1]);
    match = reg.exec(str);
  }
  return str.replace(reg, (match, p1) => {
    const string = new Function(...result, `return ${p1}`)(...result.map(v => eval(v)));
    return `${string}`
  })
};

但是实际上,题目根本没有出错,就是这样的调用形式:

highlight`Hello, ${yourName}. I am ${myName}.`

这种调用形式叫做标签模板功能。

标签模板功能

模板字符串可以紧跟在一个函数后面,函数将被用来处理这个模板字符串,这就是标签模板功能:

alert`123`
// 等同于
alert(123)

标签模板其实不是模板,而是函数调用的一种形式,函数后面紧跟的字符串就是函数的参数。

当字符串中有变量时,会将模板字符串处理为多个参数,再调用函数,比如:

const a = 5;
const b = 10;

alert`hello ${a + b} world ${a * b}`
// 等同于
alert(['hello ', ' world', ''], 5, 10)

alert的返回值就是函数处理模板字符串后的返回值,函数会接收到多个参数:

function tag(stringArr, value1, value2){
  // ...
}

// 等同于

function tag(stringArr, ...values){
  // ...
}

函数的第一个参数是一个数组,数组的成员是模板字符串中没有变量替换的部分,也就是说,变量替换只发生在各个数组成员之间

函数的其他参数,都是模板字符各个变量被替换后的值

回到题目上来

highlight`Hello, ${yourName}. I am ${myName}`.

实际上函数调用是:

function highlight(['hello, ', '. I am ', ''], yourName, myName) {}

所以可以这样:

const highlight = (strArray, ...rest) => {
  return strArray.map((v, key) => v + `${rest[key] || ''}`).join('')
};

另外,有一个String.raw方法,它可以获取一个模板字符串的原始字面量值的

比如:

let name = "Bob";
String.raw `Hi\n${name}!`;             
// "Hi\\nBob!",内插表达式还可以正常运行

以后用到的时候再看MDN的文档。

参考

  • #86 字体高亮函数@ScriptOJ
  • 标签模板@ECMAScript6入门
  • String.raw()@MDN

你可能感兴趣的:(前端练习)