如何自定义console.log,自动为传入参数打印变量名标签?
实现自动带变量名的自定义日志函数
嘿,这个需求太实用了!我之前开发的时候也烦透了每次手动写'varName: ', varName,其实完全可以实现你想要的效果,下面给你两种可行的方案:
方案一:通过调用栈解析变量名(最贴合你的需求)
这个方法利用Error对象的stack属性获取调用栈信息,然后从调用代码里提取传入的变量名,不需要用户额外写模板字符串,直接调用my.log(varName)就行:
const my = { log(...args) { // 创建一个Error来捕获调用栈 const error = new Error(); // 拆分调用栈为行数组,不同浏览器的栈结构略有差异,这里做兼容处理 const stackLines = error.stack.split('\n'); // 找到调用my.log的那一行(Chrome通常是第2行,Firefox是第3行) const callLine = stackLines[2]?.trim() || stackLines[3]?.trim(); if (!callLine) return console.log(...args); // 从调用行里提取my.log(...)中的参数部分 const paramMatch = callLine.match(/my\.log\((.*)\)/); if (!paramMatch) return console.log(...args); // 分割参数并去除空格,处理多个变量的情况 const paramNames = paramMatch[1].split(',').map(name => name.trim()); // 拼接变量名和对应的值 const logContent = args.map((value, index) => { const varName = paramNames[index] || 'unknown'; return `${varName}: ${value}`; }).join(', '); console.log(logContent); } };
测试示例:
const firstName = 'Alice'; const age = 30; const isActive = true; my.log(firstName); // 输出:firstName: Alice my.log(firstName, age, isActive); // 输出:firstName: Alice, age: 30, isActive: true
注意事项:
- 局限性:如果传入的是表达式(比如
my.log(firstName + ' Smith')),解析出来的会是表达式内容而不是变量名;另外如果代码被压缩混淆(比如生产环境构建),变量名会被替换成a、b这类短名,这个方法就失效了。 - 浏览器兼容:不同浏览器的调用栈格式可能有细微差别,需要根据实际情况调整
stackLines的索引。
方案二:使用ES6模板字符串标签函数(更可靠)
如果担心调用栈解析的兼容性问题,可以用标签函数的方式,虽然需要用户写反引号,但能更稳定地控制输出:
function log(strings, ...values) { // 遍历模板字符串片段和变量值,拼接成带变量名的日志 const logContent = strings.reduce((result, str, index) => { if (index < values.length) { // 通过对象键名特性自动获取变量名 const varName = Object.keys({ [values[index]]: values[index] })[0]; return result + str + `${varName}: ${values[index]}`; } return result + str; }, ''); console.log(logContent); }
测试示例:
const firstName = 'Bob'; log`${firstName}`; // 输出:firstName: Bob
不过这个方案本质上还是需要用户在模板里传入变量,和手动写的工作量差别不大,所以更推荐第一种方案在开发环境使用。
生产环境建议
如果是在生产环境,建议直接使用原生console.log,或者给自定义日志加环境判断,避免解析调用栈带来的性能损耗:
const my = { log(...args) { if (process.env.NODE_ENV === 'development') { // 上面的解析逻辑 } else { console.log(...args); } } };
内容的提问来源于stack exchange,提问作者Ringo
相关产品推荐
相关产品推荐

