41 votes

Appel de la taille de la pile à l'intérieur de JavaScript

Je veux tester pour de grandes piles d'appels. Plus précisément, je veux une console d'avertissement lorsque la pile d'appel de la longueur atteint 1000. Cela signifie généralement j'ai fait quelque chose de stupide, et peut conduire à des bogues subtils.

Puis-je calculer la pile d'appel de longueur dans le JavaScript?

47voto

Tim Down Points 124501

Voici une fonction qui fonctionne dans tous les principaux navigateurs, bien que cela ne fonctionnera pas dans ECMAScript 5 en mode strict, car arguments.callee et caller ont été supprimés en mode strict.

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

Exemple:

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

f(); // Alerts 3

Mise à JOUR le 1er novembre 2011

Dans l'ES5 mode strict, il n'y a tout simplement pas de moyen de parcourir la pile d'appel. La seule option qui reste est d'analyser la chaîne de caractères retournée par new Error().stack, ce qui est non-standard, pas de prise en charge universelle et évidemment problématique, et même cela peut ne pas être possible pour toujours.

Mise à JOUR le 13 août 2013

Cette méthode est également limitée par le fait qu'une fonction qui est appelée plus d'une fois dans une seule pile d'appel (par exemple, via la récursivité) va jeter getCallStackSize() dans une boucle infinie (comme l'a fait remarquer @Randomblue dans les commentaires). Une version améliorée de l' getCallStackSize() ci-dessous: il conserve une trace de fonctions qu'il a vu avant pour éviter de rentrer dans une boucle infinie. Toutefois, la valeur retournée est le nombre de différents objets de fonction dans la pile des appels avant de rencontrer une répétition plutôt que la vraie taille de la pile d'appel complète. C'est le meilleur que vous pouvez faire, malheureusement.

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;
}

2voto

Yonatan Naor Points 96

Vous pouvez utiliser ce module: https://github.com/stacktracejs/stacktrace.js

L'appel de printStackTrace renvoie la trace de la pile à l'intérieur d'un tableau, alors vous pouvez vérifier sa longueur:

var trace = printStackTrace();
console.log(trace.length());

-1voto

benvie Points 6181

Un peu en retard à la fête pour répondre à cela, mais le haut réponse est incorrecte. Ce bout de code fonctionne dans n'importe quel mode JavaScript, probablement juste au sujet de n'importe quelle version de JavaScript dans n'importe quel moteur trop:

var maxStackSize = function(i){try{(function m(){++i&&m()}())}catch(e){return i}}(0);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X