You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在标签模板字面量的tag函数内获取使用的变量属性名?

方案总结

JavaScript运行时原生没有提供标签模板函数获取插值表达式源码的能力,以下是三种可落地的实现方式:

方案1:运行时解析调用方函数源码

利用你发现的函数.toString()可看到插值表达式的特性,在tag函数内部主动获取调用栈,找到调用tag的函数,解析源码提取对应位置的插值表达式:

function tag(literals, ...vars) {
  // 获取调用栈
  const stack = new Error().stack.split('\n')
  // 找到调用tag的函数行,不同浏览器栈格式略有差异,可自行适配
  const callerLine = stack[2] // 一般第0行是Error本身,第1行是当前tag函数,第2行是调用方
  // 提取调用方函数名,或直接拿到函数引用
  const callerFuncName = callerLine.match(/at (\w+)/)?.[1]
  const callerFunc = window[callerFuncName] // 浏览器环境,node环境可对应调整
  if (callerFunc) {
    const funcStr = callerFunc.toString()
    // 解析模板字符串的插值部分,匹配tag`xxx${xxx}xxx`里的${}内容
    const interpolations = funcStr.match(/tag`[^`]*\$\{([^}]+)\}[^`]*`/)?.slice(1)
    console.log('插值表达式:', interpolations) // 这里就能拿到 ['data.name']
  }

  // 原有逻辑
  console.log(literals.raw)
  console.log(vars)
}

限制

  • 仅适用于未压缩、未混淆的源码,代码压缩后变量名、函数名会被改写,解析会失效
  • 调用栈解析逻辑需要适配不同运行环境(浏览器/Node/小程序等)
  • 性能较低,不适合高频调用的场景

方案2:编译时注入表达式源码

通过Babel插件在编译阶段收集所有标签模板的插值表达式源码,作为额外参数传入tag函数,是生产环境可用的最优方案:
示例编译效果:

// 源码
tag`Test ${data.name}`
// 编译后
tag(["Test ", ""], [data.name], ["data.name"])

你可以自己实现简单的Babel插件,遍历TaggedTemplateExpression节点,收集所有插值的expression的源码字符串,作为第三个参数传入即可。

优势

  • 运行时无额外性能损耗
  • 不受代码压缩混淆影响

限制

  • 需要修改项目编译配置

方案3:插值表达式包裹标记函数

不需要修改编译配置也不需要解析源码,仅需要调整插值的写法,用自定义函数包裹需要获取属性名的表达式:

// 标记函数,返回包含值和属性名的结构体
const $ = (obj, prop) => {
  return {
    value: obj[prop],
    propName: prop
  }
}

function tag(literals, ...vars) {
  vars.forEach(item => {
    if (item.propName) {
      console.log('属性名:', item.propName) // 拿到 name
      console.log('值:', item.value) // 拿到 data.name 的值
    }
  })
}

// 使用时写法调整为
function myfN() {
  return tag`Test ${$(data, 'name')}`
}

优势

  • 逻辑简单可靠,无环境依赖
  • 运行时性能稳定

限制

  • 需要调整原有插值的写法,不能直接写${data.name}

内容的提问来源于stack exchange,提问作者inux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:24:00