实现模板字符串解析

「真题讲解」- 实现模板字符串解析

本节介绍

ES6 推出了模板字符串的语法,用起来非常方便,本节我们就来尝试实现一下模板字符串的部分功能。

当然,真实的模板字符串是使用反引号 (``) 括起来的,本题不需要实现这个功能,只需要实现变量替换的功能即可,让我们来对这个功能的实现一探究竟吧。

知识点

  • 模板字符串
  • 正则表达式

题解

在讲解之前,先给出本题的答案,代码如下:

function strRender(str, data) {
  const re = /\$\{(\w+)\}/;
  if (re.test(str)) {
    const key = str.match(re)[1];
    str = str.replace(re, data[key]);
    return strRender(str, data);
  }
  return str;
}

或者

function strRender(str, data) {
  const re = /\$\{(\w+)\}/g;
  return str.replace(re, (match, key) => data[key]);
}

题解分析

有了上一章正则表达式的基础,本题实现起来就非常简单了,只需要匹配字符串中被 ${} 包裹的内容,也就是字符串中需要被填充的变量,然后把它替换成实际的数据即可,正则匹配流程图如下:

https://doc.shiyanlou.com/courses/9328/2086340/7bb0b2ff5b3c413af7a2303ebbb18bed-0

可以看到,首先匹配的是 ${,然后匹配任意单字字符重复 1 次或多次的情况,最后匹配 },这样就拿到了字符串中诸如 ${name} 形式的内容。

注意上图中被虚线框起来的 Group #1 部分,这里用到了捕获括号的语法,这样我们就可以拿到变量的 key 值,也就是 ${xxx} 中的 xxx

拿到了变量的 key 值之后,就能取到需要被替换的数据了,就可以用 replace 方法把 ${xxx} 替换成真正的数据。

最后实现代码如下:

function strRender(str, data) {
  const re = /\$\{(\w+)\}/;

  // 如果字符串中存在 ${xxx},说明还有变量没有被替换,才执行后面的逻辑
  if (re.test(str)) {
    // 使用 match 方法获取 key 值
    const key = str.match(re)[1];

    // 使用 replace 方法替换变量为真实的数据
    str = str.replace(re, data[key]);

    // 注意这里的逻辑,递归调用自身,直到字符串中不存在 ${xxx}
    return strRender(str, data);
  }
  return str;
}

上面的代码中,我们使用了递归的逻辑,因为每次匹配只匹配到了第一个值就终止了,所以要递归调用自身,直到字符串中不存在 ${xxx},才算结束。

其实,只需要在正则中加入全局搜索修饰符,即可轻松优化代码,代码如下所示:

function strRender(str, data) {
  // 正则中加入全局搜索修饰符,也就是在尾部加一个 g
  const re = /\$\{(\w+)\}/g;
  return str.replace(re, (match, key) => data[key]);
}

这里 replace 函数的替换值就不再是一个字符串了,而是一个回调函数,这个回调函数每次匹配都会调用,每次调用时会把匹配到了的模板变量替换为真实的数据,这样就不需要递归调用了。用到的原理就是 replace 函数可以指定一个函数作为参数,如果对具体的语法不太明白,可以参考 MDN

本节总结

本节我们通过正则轻松实现了模板字符串解析的部分功能,本节的重点是:

  • 捕获括号获取每个变量。
  • replace 方法中的回调函数。

replace 这个方法的用途非常灵活,希望做完本题后,同学们能对 replace 方法的理解更进一步。

进入下一章节

你可能感兴趣的:(蓝桥杯-WEB,正则表达式,javascript,前端)