0

現在の関数の前に呼び出されたすべての関数の名前を取得して、ある種のスタック トレースを取得したいとします。

私はこのようなことをします:

        var callee;
        var caller;
        var _args = arguments;
        var check = 0;
        do {
                    check++;

                    callee = _args.callee;
                    caller = callee.caller;

                    var msg = 'Check ' + check + ' - ' + callee.name 
                            + ' has been called by: ' + caller.name;
                    console.log(msg);

                    if (caller) {
                        // Get this caller's arguments
                        _args = caller.arguments;
                    } else {
                        reached_end = true;
                    }

        } while (!reached_end);

ほとんどの場合、これで問題なく動作します。しかし、ときどき無限ループに陥ってしまうことがあります。そして、私はそれについて何ができますか?

これが私の無限ループの出力です:

    Check 1 - __parent__ has been called by: add
    Check 2 - add has been called by: afterComponentStartup
    Check 3 - afterComponentStartup has been called by: _launchComponents [arg0:"startup"]
    Check 4 - _launchComponents has been called by: beforeActionNext
    Check 5 - beforeActionNext has been called by: beforeAction
    Check 6 - beforeAction has been called by: afterComponentInitialize
    Check 7 - afterComponentInitialize has been called by: _launchComponents [arg0:"startup"]
    Check 8 - _launchComponents has been called by: beforeActionNext
    Check 9 - beforeActionNext has been called by: beforeAction
    Check 10 - beforeAction has been called by: afterComponentInitialize
    Check 11 - afterComponentInitialize has been called by: _launchComponents [arg0:"startup"]
    Check 12 - _launchComponents has been called by: beforeActionNext
    Check 13 - beforeActionNext has been called by: beforeAction
    Check 14 - beforeAction has been called by: afterComponentInitialize
    Check 15 - afterComponentInitialize has been called by: _launchComponents [arg0:"startup"]
    Check 16 - _launchComponents has been called by: beforeActionNext
    Check 17 - beforeActionNext has been called by: beforeAction
    Check 18 - beforeAction has been called by: afterComponentInitialize
    Check 19 - afterComponentInitialize has been called by: _launchComponents [arg0:"startup"]
    Check 20 - _launchComponents has been called by: beforeActionNext
    Check 21 - beforeActionNext has been called by: beforeAction
    Check 22 - beforeAction has been called by: afterComponentInitialize
    Check 23 - afterComponentInitialize has been called by: _launchComponents [arg0:"startup"]
    Check 24 - _launchComponents has been called by: beforeActionNext
    Check 25 - beforeActionNext has been called by: beforeAction
    Check 26 - beforeAction has been called by: afterComponentInitialize
4

3 に答える 3

4

arguments.callee.caller関数参照を指し、各コール スタック内の関数ごとに 1 つだけ存在します。

関数が呼び出されるたびに、callerプロパティが設定されます。つまり、再帰関数で発生するように、同じ関数がコール スタックで複数回呼び出された場合、以前の値はリセットされ、callerそれ自体を指すようになります。これが無限ループの原因です。

したがって、アルゴリズムでは、callee === callee.callerこれが起こらないようにするためにブレークする必要があるポイントに到達した場合.

于 2013-03-23T02:02:28.690 に答える
1

呼び出し元を配列に追加し、次の呼び出し元が配列にあるかどうかを確認する必要があります。もしそうなら、あなたは循環的または再帰的な呼び出し構造を持っています。これを試して:

var args = arguments;
var callee = args.callee;
var caller = callee.caller;

var stack = [callee];

while (caller) {
    if (stack.indexOf(caller) < 0) {
        stack.push(caller);
        args = caller.arguments;
        callee = args.callee;
        caller = callee.caller;
    } else break;
}

console.log(stack);
于 2013-03-23T01:39:35.040 に答える