2013-03-16 13 views
6

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"); 
} 
+0

デッドコード除去ツールを使用してこのようなことを実行できるかどうかは疑問です。私が必要とするすべての機能を定義し、必要な機能を必要とする機能だけを呼び出すことができます。次に、デッドコード除去ツールを使用して、スクリプトで使用されていないすべての機能を削除します。 –

+1

ここで何を達成しようとしていますか? – smk

+0

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee –

答えて

13

Esprimaお手伝いができます。これは、静的コード解析を行うのに役立つ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); 

は明らかに、これは多くの価値を提供するために多くの援助を必要とするが、それはあなたが開始する何が可能ですし、どこのいくつかのアイデアを与えるかもしれません。

+0

Google Chromeでは、 'console。log(funcs)は、配列の内容を出力するのではなく、 'Array [4]'をコンソールに出力します。代わりに 'funcs'の内容をコンソールに出力したい場合は、' console.log(JSON.stringify(funcs)); 'を使うことができます。 –

+0

同様のソリューションを作成しましたが、今は関数宣言と関数式呼び出しだけを解析します https://github.com/sanex3339/javascript-obfuscator/blob/dev/src/StackTraceAnalyzer.ts –

-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を呼び出します。

または

ネイティブ関数を除外したいと仮定しています。

function addEventListener() { 
    [native code] 
} 

あなたのループ内でパターン/\[native code\]/と一致すると一致する機能を省略することができます:Firefoxでは、Function.toString()はネイティブ関数のため、形になり、関数本体を、返します。

+0

あなたのコードは、関数が呼び出されたときに '.call()'が呼び出されると想定しています。 – Pointy

+0

これのデモンストレーションを作成できる方法はありますか(これらの機能がどのように使用されるのか理解できるように)?また、どのループを参照していますか?このコードサンプルではforループまたはwhileループは表示されません。 –

1

基本的にはできません。

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

あなたが戻ってスタックをトレースし、後方にそれを実行したい場合は、このような質問は解決策があります:あなたはおそらく探しているものを達成するためにHow can I get a Javascript stack trace when I throw an exception?

を、あなたはあなたの機能が継承するジェネリッククラスを作成することができ、それらに関数呼び出しを割り当てる独自の実装されたメソッドを使用します。

+0

JavaScriptは通常の言語では記述できません。ファンクションボディのコードをクランチするためには、完璧なパーサが必要です。http://www.codinghorror.com/blog/2008/06/regular-expressions-now-you-have-two-problems.html –

+0

なぜ私はそれを最高で信頼できないと呼ぶのか)。 質問の目的がコードを分析するのであれば、スタックをトレースすることでそのスタックを利用することができます。 – Jaibuu

2

興味深い質問です。私はあまりにもその背後にある動機に疑問を呈しています...うまくいけば、アプリケーションの構造をよりよくデバッグしたり理解したりすることができればうれしいです。あなたはそれぞれの機能に結び付けることができれば、あなたはで呼び出し先を取得することができちょうどそこにそれを投げる...

arguments.callee.name 

とすることを書く

はここWILDアイデアですグローバル変数(多分、各キーが関数の名前であり、値が関数名の配列であるオブジェクト)。

+0

それは私がもともと考えていたものですが、いくつか問題があります。まず、すべての単一の機能を変更する必要はありません。依存グラフを手で描くこともできます。第二に、私はOPが依存グラフを静的に決定したいと思う。このソリューションは、プログラムの実行時にのみ機能し、すべての関数が完全なグラフを作成するために呼び出すことができるすべての関数によって呼び出された場合にのみ再び機能します。これは、プログラム内のすべての可能なコードパスを並行して処理するようなものです。 JavaScriptは非決定論的プログラミング言語ではありません。 –

+0

@AaditMShahそうです、私はそれも考えました。しかし、興味深いことに、関数に 'console.dir(arguments)'を追加してChromeでConsoleを見ると、 'arguments.callee。 .Closure'にドリルダウンして、期待される関数を与えることができます(funcB 、funcC、およびfuncD)。しかし、私は ''にプログラム的にアクセスする方法を知らない。 devtoolsの組み込み関数でなければなりませんか? –

関連する問題