如何在JavaScript函数内获取外部传入变量的名称?
实现方案
首先明确:JavaScript是值传递,函数内部无法直接获取传入参数的原始变量名——因为函数接收的是变量的值,而非变量本身的标识符信息。不过可以通过一些hack手段实现你要的效果,以下是可行方案:
方案1:解析调用栈提取变量名
利用Error对象的调用栈信息,解析调用代码中的变量名,示例代码如下:
function test(obj) { try { // 获取调用栈,拆分出调用test的那一行 const callStack = new Error().stack.split('\n'); // 不同环境栈帧索引可能有差异,这里取第2帧(Chrome/Firefox测试有效) const callLine = callStack[2].trim(); // 匹配test(xxx)中的xxx部分 const varNameMatch = callLine.match(/test\(([^)]+)\)/); if (varNameMatch) { const varName = varNameMatch[1].trim(); // 替换成你已有的递归格式化逻辑 const formattedContent = JSON.stringify(obj, null, 2); console.log(`${varName}: ${formattedContent}`); } } catch (e) { // 兼容栈解析失败的情况,降级输出 const formattedContent = JSON.stringify(obj, null, 2); console.log(formattedContent); } } // 调用示例 const data = {a: 1, b: {c: 3, d: [4,5]}}; test(data); // 输出: // data: { // "a": 1, // "b": { // "c": 3, // "d": [ // 4, // 5 // ] // } // }
注意事项
- 兼容性:不同浏览器/Node.js版本的调用栈格式可能不同,需要根据实际环境调整栈帧索引和正则表达式;
- 代码压缩限制:如果代码经过生产环境压缩(变量名被混淆成
a/b这类),此方法会失效; - 特殊调用场景:如果调用时直接传字面量(如
test({a:1})),会提取出{a:1}而非变量名,不符合预期。
方案2:接受额外变量名字符串(最可靠)
如果不想依赖hack手段,最稳妥的方式是额外传递变量名作为参数,虽然多传一个参数,但避免了所有兼容性问题:
function test(obj, varName = 'data') { const formattedContent = JSON.stringify(obj, null, 2); console.log(`${varName}: ${formattedContent}`); } // 调用示例 const data = {a:1, b:2}; test(data, 'data');
方案3:标签函数调用(改变调用方式)
如果可以接受调整调用语法,用ES6标签函数也能实现,但调用时需要用模板字符串语法:
function test(strings, obj) { const varName = strings.raw[0]; const formattedContent = JSON.stringify(obj, null, 2); console.log(`${varName}: ${formattedContent}`); } // 调用示例 const data = {a:1, b:2}; test`data`; // 注意是反引号包裹变量名
总结
没有完美的“无额外传参且完全可靠”的实现方式——因为JavaScript的语言特性限制了函数内部无法直接获取参数的原始变量名。如果必须坚持test(data)的调用方式,只能选择方案1的栈解析hack,但要做好兼容和降级处理;追求稳定性的话,方案2是最优选择。
内容的提问来源于stack exchange,提问作者M A
相关产品推荐
相关产品推荐

