你知道什么是标签函数么?

大家好,我卡颂。

JS中有一类特殊的函数 ------ 标签函数,用于自定义模版字符串的处理逻辑。

不同于一般函数形如fn(argA, argB)的执行方式,标签函数可以直接跟在模版字符串前面,比如:

js 复制代码
tagFn`hello ${name}`

本文来聊聊标签函数都有哪些有意思的应用。

欢迎围观朋友圈、加入人类高质量前端交流群,带飞

内置的标签函数

JS中只有一个内置标签函数 ------ String.raw,用于获取模字符串的原始字符串形式,即:

  • 处理替换(例如替换${name}为变量实际的值)

  • 不处理转义序列(例如 \n)

对于如下代码:

js 复制代码
const name = 'Ka Song';

const s1 = `Hello \n ${name}`
const s2 = String.raw`Hello \n ${name}`

console.log分别打印s1s2的结果如下:

之所以s1有换行符,而s2没有,是因为默认情况,模版字符串会处理转义字符(比如这里的\n),而String.raw不会处理。

要实现一个简易的String.raw也很简单,比如下面的myRaw,其中:

  • strings参数是保存原始字符串的数组

  • values参数是保存所有替换变量的数组

js 复制代码
function myRaw(strings, ...values) {
    let result = '';
    for (let i = 0; i < strings.length; i++) {
        result += strings.raw[i] || strings[i];
        if (i < values.length) {
            result += values[i];
        }
    }
    return result;
}

对于模版字符串你好${1}我是${2}${3}谢谢

  • strings参数如下:
js 复制代码
["你好", "我是", "", "谢谢"]
  • values参数如下:
js 复制代码
[1, 2, 3]

myRaw方法会依次从stringsvalues中取值拼接字符串。

身份标签

标签函数的一个有意思的应用场景是定义身份标签 ,也就是告诉编译器接下来这段模版字符串是什么语言

举个例子,我们在JS文件中定义两个变量(markupstyle),IDE此时只认为这是两个普通的模版字符串(没有语法高亮):

现在,我们将String.raw分别重命名为htmlcss

js 复制代码
const html = String.raw;
const css = String.raw;

IDE有了提示信息后,就能根据提示中的语言对模版字符串进行高亮了:

自定义标签函数

刚才我们已经实现了String.raw的简易版本,在此基础上做一点修改,就能实现一个将模版字符串转换为大写形式的标签函数:

js 复制代码
function upperCase(strings, ...values) {
  let result = "";
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < values.length) {
      result += values[i];
    }
  }
  return result.toUpperCase();
}

使用方式如下:

js 复制代码
let x = "Hello";
let y = "kasong";
const result = upperCase`${x}, ${y}!`; 

输出:

复制代码
HELLO, KASONG!

大体来说,标签函数的应用场景可以分为几类:

1. 语法校验

比如,对于HTML字符串,可以使用标签函数来自动转义模板字符串中的特殊字符,以防止XSS(跨站脚本攻击)。下面是一个代码示例:

js 复制代码
function safeHtml(strings, ...values) {
  let result = strings[0];
  for (let i = 1; i < strings.length; i++) {
    let val = String(values[i - 1]);
    result += val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    result += strings[i];
  }
  return result;
}

使用方式如下:

js 复制代码
let userSuppliedInput = "<img src=x onerror=alert('XSS')>";
const result = safeHtml`<div>${userSuppliedInput}</div>`;

输出:

html 复制代码
<div>&lt;img src=x onerror=alert('XSS')&gt;</div>

对于后端应用,可以创建一个标签函数,用于转义SQL语法中不安全的部分,防止SQL注入。

2. 国际化和本地化

标签函数可以用于处理模板字符串中的文本,使其根据用户的语言和地区进行适当的转换。

3. 创建DSL

标签函数可以用于解析模板字符串中的特定语法,从而创建DSL(领域特定语言)。

比如,可以实现一个css标签函数,解析字符串中的css语法。使用方式如下:

js 复制代码
const style = css`color: ${color}; font-size: ${fontSize}px;`;

总结

标签函数属于ES6特性,所以整体兼容性很不错:

当我们需要处理模版字符串时,可以考虑自定义一个标签函数。

相关推荐
walking957几秒前
重新学习前端之设计模式与架构
前端·javascript·面试
walking9573 分钟前
重新学习前端之TypeScript
前端·javascript·面试
walking9574 分钟前
重新学习前端之Linux
前端·vue.js·面试
walking9574 分钟前
重新学习前端之CSS
前端·vue.js·面试
walking9574 分钟前
重新学习前端之Git
前端·vue.js·面试
walking9575 分钟前
重新学习前端之小程序
前端
魔术师Grace7 分钟前
AI让我退化成原始人了
前端·程序员
铁皮饭盒8 分钟前
今天你会学到这些关键词
前端·后端
李剑一9 分钟前
耗时 2 小时!我复刻了全网超火的通透 3D 水晶球动效,Vue3+Three.js 做出高级视觉特效
前端·three.js
oil欧哟16 分钟前
🤔 很长时间没写文章了,分享一下最近的一些思考
前端·后端