使用 javascript 确定 javascript 中的堆栈深度

Posted

技术标签:

【中文标题】使用 javascript 确定 javascript 中的堆栈深度【英文标题】:determine stack depth in javascript using javascript 【发布时间】:2012-01-13 14:23:12 【问题描述】:

有没有办法通过使用 javascript 本身来确定在 javascript 中执行的所有函数的堆栈深度?

我认为这可能涉及修改Function 原型,但我真的不知道。

此外,能够在堆栈深度足够高的任何时候中断会很好。

原因是我有一个stack overflow error in IE which is apparently not debuggable。我很懒惰,我宁愿不必通过我维护的代码来寻找原因。

感谢您帮助我的懒惰。

【问题讨论】:

您可以将一个函数告诉另一个函数并递增一个全局变量,直到浏览器本身引发堆栈溢出错误。然后你打印你的计数器变量,你有一个粗略的堆栈深度值。 【参考方案1】:

ECMAscript 支持 Function.prototype.caller 属性已经有一段时间了。即使它在 ES5 strict 中被弃用,IE 仍然应该支持它。因此,您基本上可以通过所涉及的功能循环往上。

function one() 
   two();


function two() 
   three();


function three() 
    var caller = three.caller;

    console.log('caller was: ', caller.name);

    while( caller = caller.caller ) 
           console.log('caller was: ', caller.name);
    


(function outer() 
    one();
());

这将输出:

caller was: two
caller was: one
caller was: _outer

因此,如果您知道错误发生在哪个函数中,那么您就可以从最初调用该方法的方式中得到答案。如果您只是在深度之后,您可以计算在caller.caller 属性上进行了多少次交互。至少 IE8 应该支持“debugger”语句,您可以在该脚本中调用它来将调试器带到舞台上。

【讨论】:

这看起来很像我想要的......但问题是我需要以某种方式将其应用于所有函数,而不必将其添加到他们的代码中。你懂我的意思吗?谢谢。 @user420667:我认为在 Function.prototype 上没有任何“简单”的方法可以做到这一点。您基本上需要对所有对象进行递归循环(以window 开头)并检查函数。如果找到,则需要挂钩/修补该方法并调用上面提供的代码。可能会奏效。 哦,好吧..所以每个函数都有类似的东西...... newFunction = function() oldFunction(args); if(CallerDepth() > MaxAllowedDepth) 调试器; ;旧功能 = 新功能; ???我不认为这是完全正确的。另外,就像您说的那样,确保以某种方式在任何其他函数之前被调用,并确保在修改任何函数之前创建要迭代的函数列表。 “即使它在 ES5 strict 中已被弃用”。没有足够的警告,这应该被使用。 @jAndy 调试目的很好。但是,您应该在生产环境中运行 es5 strict【参考方案2】:
function stackDepth() 
  var c=stackDepth.caller, depth=0;
  while (c)  c = c.caller; depth++; 
  return depth;

Chrome 似乎认为控制台的堆栈深度已经是 3,因此可能对于每个 JavaScript 环境,您都需要确定初始基线深度并从中减去。

stackDepth(); // => 3
(function()return stackDepth();)(); // => 4

【讨论】:

有趣。我想知道 3 个更高级别的对象是什么。窗户?文件?

以上是关于使用 javascript 确定 javascript 中的堆栈深度的主要内容,如果未能解决你的问题,请参考以下文章

Array.shift和链接列表在JavaScript中的等价物之间的性能差异是什么

为什么 Web 开发人员需要学习一个 JavaScript 框架?

使用JavaScript

前端——JavaScript

jQuery

04004_JavaScript