如何绑定console.log到函数调用显示调用处行号并优化polyfill调用
解决方案
你遇到的核心矛盾是:要让console.log的调用位置出现在业务代码(main.js)而非polyfill代码中,才会显示正确行号,所以你现在用返回绑定后log函数的方式,但需要额外加括号执行。以下是几种可行的实现方案:
方案1:直接内部调用(无额外括号,行号显示polyfill文件)
如果可以接受行号显示为polyfill.js的行,直接修改最后一行代码,调用绑定好的log函数即可,完全匹配原生调用方式:
// 替换原return行 (window.console.log.bind(window.console, name + ': ' + endt + 'ms'))();
方案2:自动执行绑定函数(无额外括号,行号正确,兼容IE8+)
通过重写返回函数的valueOf和toString方法,利用JS表达式自动拆箱的特性实现隐式调用,调用方式完全和原生一致,行号显示为业务代码调用处:
console.timeEnd = function(name) { var datenow = Date.now(); name = name ? name : 'default'; if (!timers[name]) { console.warn('Timer "' + name + '" does not exist.'); return function() {}; } var endt = datenow - timers[name]; delete timers[name]; var logFn = window.console.log.bind(window.console, name + ': ' + endt + 'ms'); // 隐式执行逻辑 logFn.valueOf = logFn.toString = function() { this(); return ''; }; return logFn; };
- 注意:该方案在IE下单独调用
console.timeEnd()即可自动触发打印,现代浏览器中如果未自动触发,可以在调用前加一元运算符(如+console.timeEnd('xxx')),不需要额外加括号。
方案3:eval实现(无额外括号,行号正确)
如果可以接受使用eval,利用全局eval的执行上下文特性,可以实现正确行号显示:
console.timeEnd = function(name) { var datenow = Date.now(); name = name ? name : 'default'; if (!timers[name]) { console.warn('Timer "' + name + '" does not exist.'); return; } var endt = datenow - timers[name]; delete timers[name]; var logContent = JSON.stringify(name + ': ' + endt + 'ms'); // 全局eval执行log调用 window.eval('console.log(' + logContent + ')'); };
- 注意:该方案在部分IE版本中可以正确显示业务代码的调用行号,不同IE小版本表现略有差异。
方案4:构建时代码替换(无感知,行号完全正确)
如果项目有构建流程,可以在babel/webpack打包阶段,自动将所有console.timeEnd(xxx)的调用替换为console.timeEnd(xxx)(),业务代码完全按照原生写法即可,不需要做任何修改,行号100%正确。
内容的提问来源于stack exchange,提问作者samar
相关产品推荐
相关产品推荐

