你如何找出 JavaScript 中的调用者函数?

IT技术 javascript callstack
2021-01-11 06:03:34
function main()
{
   Hello();
}

function Hello()
{
  // How do you find out the caller function is 'main'?
}

有没有办法找出调用堆栈?

6个回答

请注意,此解决方案已弃用,根据 MDN 文档不应再使用

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller


function Hello()
{
    alert("caller is " + Hello.caller);
}

请注意,此功能是非标准的,来自Function.caller

非标准
此功能是非标准的,不在标准轨道上。不要在面向 Web 的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,未来可能会改变行为。


以下是 2008 年的旧答案,现代 Javascript 不再支持该答案:

function Hello()
{
    alert("caller is " + arguments.callee.caller.toString());
}
“'caller'、'callee' 和 'arguments' 属性可能无法在严格模式函数或调用它们的参数对象上访问”——它们在 ES5 中已被弃用,并在严格模式下被删除。
2021-03-13 06:03:34
自从这篇文章于 2011 年列出以来,此方法已过时。现在首选方法是 Function.caller(截至 2015 年)。
2021-03-22 06:03:34
arguments可以在严格模式下从函数内部访问,弃用它是愚蠢的。只是不是来自外部的 function.arguments。此外,如果您有一个命名参数,它的 arguments[i] 形式将不会跟踪您对函数内的命名版本所做的更改。
2021-03-25 06:03:34
如果您不使用严格模式,它只会起作用。所以删除'use strict';可能会有所帮助。
2021-04-01 06:03:34
arguments.callee.caller.name 将获得函数的名称。
2021-04-03 06:03:34

堆栈跟踪

您可以使用浏览器特定代码找到整个堆栈跟踪。好在有人已经做到了这是GitHub 上项目代码

但并非所有消息都是好消息:

  1. 获取堆栈跟踪真的很慢,所以要小心(阅读本文了解更多)。

  2. 您需要为堆栈跟踪定义函数名称以使其清晰易读。因为如果你有这样的代码:

    var Klass = function kls() {
       this.Hello = function() { alert(printStackTrace().join('\n\n')); };
    }
    new Klass().Hello();
    

    谷歌浏览... kls.Hello ( ...器会发出警报,但大多数浏览器都希望在关键字后有一个函数名称function,并将其视为匿名函数。Klass如果您不为kls函数提供名称,那么即使是 Chrome 也无法使用该名称

    顺便说一句,您可以将选项传递给函数 printStackTrace,{guess: true}但我没有发现这样做有任何真正的改进。

  3. 并非所有浏览器都会为您提供相同的信息。即参数、代码列等。


调用函数名称

顺便说一句,如果您只想要调用者函数的名称(在大多数浏览器中,但不是 IE),您可以使用:

arguments.callee.caller.name

但请注意,此名称将是function关键字之后的名称我发现没有办法(即使在谷歌浏览器上)在不获取整个函数的代码的情况下获得更多。


调用函数代码

并总结其余的最佳答案(由 Pablo Cabrera、nourdine 和 Greg Hewgill 提供)。您可以使用的唯一跨浏览器和真正安全的东西是:

arguments.callee.caller.toString();

这将显示调用者函数代码可悲的是,这对我来说还不够,这就是为什么我给你提示 StackTrace 和调用函数名称(尽管它们不是跨浏览器的)。

Function.caller 但是,不会在严格模式下工作。
2021-03-21 06:03:34
也许您应该Function.caller根据@Greg 的回答添加
2021-03-27 06:03:34

我知道你提到了“在 Javascript 中”,但如果目的是调试,我认为只使用浏览器的开发人员工具更容易。这是它在 Chrome 中的样子: 在此处输入图片说明 只需将调试器放在您要调查堆栈的位置。

这是一个古老的问题……但这绝对是当今最有效的现代方法。
2021-03-10 06:03:34

我通常(new Error()).stack在 Chrome 中使用好消息是,这还为您提供了调用者调用该函数的行号。缺点是它将堆栈的长度限制为 10,这就是我首先来到这个页面的原因。

(我使用它在执行期间在低级构造函数中收集调用堆栈,以便稍后查看和调试,因此设置断点没有用,因为它会被击中数千次)

(new Error("StackLog")).stack.split("\n") 使它更好读。
2021-03-11 06:03:34
您能否就您提供的解释添加更多描述?
2021-03-24 06:03:34
这是我'use strict';到位后唯一可以开始工作的事情给了我我需要的信息——谢谢!
2021-03-24 06:03:34
关于堆栈长度的限制……您可以使用“Error.stackTraceLimit = Infinity”更改它。
2021-04-07 06:03:34

您可以获得完整的堆栈跟踪:

arguments.callee.caller
arguments.callee.caller.caller
arguments.callee.caller.caller.caller

直到来电者是null

注意:它会导致递归函数无限循环。

抱歉回复晚了,但我之前没有看到您的评论;仅在递归情况下它不起作用,在其他情况下它应该起作用。
2021-04-08 06:03:34