7

JavaScript で、別の関数によって呼び出されるすべての関数のリストを取得することは可能ですか? 関数の依存関係のツリーを作成して、スクリプト内の関数が互いにどのように関連しているか (および、どの関数が他の関数によって必要とされるか) を分析したいと考えています。

例えば:

getAllCalledFunctions(funcA); //this should return [funcB, funcC, funcD], since these are the functions that are required by funcA.

function getAllCalledFunctions(functionName){
    //how should I implement this?
}

function funcA(){
    funcB();
    funcC();
}

function funcB(){
    funcD();
}

function funcC(){
    funcD();
}

function funcD(){
    console.log("This function is called by funcC and funcD");
}
4

4 に答える 4

15

エスプリマがあなたを助けるかもしれません。これは、静的コード分析を行うのに役立つ Javascript パーサーです。

簡単な例を次に示します ( http://jsfiddle.net/fyBvT/ ):

var code = 'function funcA() { funcB(); funcC(); } function funcB(){ funcD(); } function funcC() { funcD(); } function funcD(){ console.log("This function is called by funcC and funcD"); }';
var syntax = esprima.parse(code);

var funcs = [];
_.each(syntax.body, function(i) {
    if (i.type == 'FunctionDeclaration') {
        var func = {name: i.id.name};

        _.each(i.body.body, function(j) {
            if (j.type == 'ExpressionStatement' && j.expression.type == 'CallExpression') {
                func.calls = func.calls || [];
                func.calls.push(j.expression.callee.name);
            }
        });

        funcs.push(func);
    }
});

console.log(funcs);

明らかに、多くの価値を提供するには多くの助けが必要ですが、何が可能で、どこから始めればよいかについてのアイデアが得られるかもしれません。

于 2013-03-16T05:28:12.857 に答える
2

興味深い質問です。私もその背後にある動機に疑問を持っています...うまくいけば、それはアプリケーションの構造をよりよくデバッグまたは理解するためだけのものです。

これがワイルドなアイデアです:それを捨てるだけです...

各関数に結び付けることができる場合は、次の方法で呼び出し先を取得できます。

arguments.callee.name

そして、それをグローバル変数に書き込みます(おそらく、各キーが関数の名前であり、値が関数名の配列であるオブジェクト)。

于 2013-03-16T05:21:37.177 に答える
1

基本的に、できません。

オブジェクト/関数は、関数の Java スクリプト コード自体で正規表現を実行しない限り、実行しない限り何を実行するかわかりません..せいぜい信頼性がありません。

スタックをさかのぼって追跡したい場合は、次のような質問に解決策があります:例外をスローしたときに Javascript スタック トレースを取得するにはどうすればよいですか?

おそらく探しているものを実現するには、関数呼び出しを割り当てる独自の実装メソッドを使用して、関数が継承する汎用クラスを作成できます。

于 2013-03-16T05:12:44.467 に答える
-3

明らかな答えは、次のようなものです。

var origCall = Function.prototype.call;
Function.prototype.call = function (thisArg) {
    console.log("calling a function");

    var args = Array.prototype.slice.call(arguments, 1);
    origCall.apply(thisArg, args);
};

しかし、これは実際にはすぐに無限ループに入ります。これは、呼び出すという行為console.log自体が関数呼び出しを実行し、それが console.log を呼び出し、関数呼び出しを実行し、それが を呼び出すconsole.logためです...

また

ネイティブ関数を除外したいと思っていると思います。Firefox ではFunction.toString()、関数本体を返します。ネイティブ関数の場合、次の形式になります。

function addEventListener() { 
    [native code] 
}

ループ内のパターン/\[native code\]/を一致させ、一致する関数を省略することができます。

于 2013-03-16T05:01:05.047 に答える