JavaScript 更改控制台调用堆栈

JavaScript Change console call stack

正确的行为

当我直接从一个函数调用 console.log() 时,我调用的堆栈(函数和文件)在开发工具控制台中是正确的,正如预期的那样。

main.js:

function main() {
    // Works correctly
    console.log('Hello from main()!');
}

控制台:

Hello from main()!    ...    main.js:3                       

我想要什么

现在,当我添加第二个名为 debug.js 的文件并从那里调用 console.log 时,我调用的文件是 debug.js,这是正确的...但是我需要 debug() 才能像在 main.js 中调用一样进行记录。我需要以某种方式修改调用者、堆栈或跟踪以欺骗 console.log() 它是从 main.js 调用的,而实际上它是从 deubg.js.

代码

debug.js:

function debug(msg) {
   console.log(msg)
}

main.js

function main() {
   debug('Hello world!') // debug() in debug.js
}

行为

当前行为:

Hello world!    ...    debug.js:2

我想要的行为:

Hello world!    ...    main.js:3

正如 WHATWG specification 所说,每个功能(错误、警告、日志等)的控制台输出都是特定于实现的:

The printer operation is implementation-defined

碰巧,基于 chromium 的浏览器在打印 console.log 的结果时显示调用堆栈的当前 (不是完整的调用堆栈),你赢了' 能够更改此行为,因为这与 JavaScript 引擎相关(V8 用于基于铬的浏览器),并且无法通过 JavaScript 代码进行自定义。

唯一允许您显示完整调用堆栈的 JavaScript 标准是 console.trace whose specification is here: https://console.spec.whatwg.org/#trace

它会为您的示例代码显示如下内容:

这可以通过创建 Error 实例 new Error() 来完成,它将以字符串形式保存跟踪,如下所示。

function debug(...args) {
    const error = new Error();
    console.log(...args, error.stack.replace(/.+\n.+\n/, ''))
}

尽管MDN Error stack document says it's a non standard property but seems all browser has support for that Browser compatibility

我认为这里的问题是控制台日志通常是从它运行的任何地方执行的。但是,如果您要传回执行控制台日志的函数,这可能会如您所愿。你能试试下面的代码吗?

尝试 #1

debug.js:

function debug(msg) {
   return (function(msg) { console.log(msg) })(msg)
}

main.js:

function main() {
   debug('Hello world!')
}

如果还是不行,你可以试试这个吗:

尝试#2

debug.js:

function debug() {
   return function(msg) { console.log(msg) }
}

main.js:

function main() {
   debug()('Hello world!')
}

您可以做的是:

const log = console.log // for future use, preserve the default function
console.log = (...args) => {
    console.trace(...args)
}

在节点上:

console.log = (...args) => {
    console.trace(...args, path.basename(__filename))
}

要得到这样的东西:

const path = require("path");
console.log = (...args) => {
  console.trace(...args, path.basename(__filename))
}

function f() {
  return function g() {
    console.log("test")
  }
}

f()()