在JavaScript中调用堆栈大小

Ran*_*lue 41 javascript debugging

我想测试大型调用堆栈.具体来说,当调用堆栈长度达到1000时,我想要一个控制台警告.这通常意味着我做了一些愚蠢的事情,并且可能导致细微的错误.

我可以在JavaScript中计算调用堆栈长度吗?

Tim*_*own 47

这里是一个将在所有主要浏览器中运行的功能,但它不会在工作的ECMAScript 5严格模式,因为arguments.calleecaller已经在严格的模式被删除.

function getCallStackSize() {
    var count = 0, fn = arguments.callee;
    while ( (fn = fn.caller) ) {
        count++;
    }
    return count;
}
Run Code Online (Sandbox Code Playgroud)

例:

function f() { g(); }       
function g() { h(); }       
function h() { alert(getCallStackSize()); }       

f(); // Alerts 3
Run Code Online (Sandbox Code Playgroud)

更新2011年11月1日

在ES5严格模式下,根本无法导航调用堆栈.剩下的唯一选择是解析返回的字符串new Error().stack,这是非标准的,不是普遍支持的,显然有问题,甚至这可能永远不可能.

更新2013年8月13日

这个方法也受到以下事实的限制:在一个调用堆栈中多次调用的函数(例如通过递归)会抛出getCallStackSize()无限循环(如注释中的@Randomblue所指出的).getCallStackSize()下面是一个改进版本:它跟踪之前看到的功能,以避免进入无限循环.但是,返回值是在遇到重复之前callstack中不同函数对象的数量,而不是完整调用堆栈的真实大小.不幸的是,这是你能做的最好的事情.

var arrayContains = Array.prototype.indexOf ?
    function(arr, val) {
        return arr.indexOf(val) > -1;
    } :
    function(arr, val) {
        for (var i = 0, len = arr.length; i < len; ++i) {
            if (arr[i] === val) {
                return true;
            }
        }
        return false;
    };

function getCallStackSize() {
    var count = 0, fn = arguments.callee, functionsSeen = [fn];

    while ( (fn = fn.caller) && !arrayContains(functionsSeen, fn) ) {
        functionsSeen.push(fn);
        count++;
    }

    return count;
}
Run Code Online (Sandbox Code Playgroud)

  • +1尼斯解决方案.万一有人遇到这个问题:在Chrome的开发者工具中,它会发出"6"警告,但这是因为在使用控制台时,看似有3个其他功能在幕后执行. (9认同)