在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 :(得分:14)
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);
显然,这需要很多帮助来提供很多价值,但它可能会让你知道什么是可能的,从哪里开始。
答案 1 :(得分:2)
有趣的问题。我也质疑它背后的动机......希望它只是为了更好地调试或理解应用程序的结构。
如果你可以绑定每个功能,你可以通过以下方式获得被叫方:
arguments.callee.name
将其写入全局变量(可能是一个对象,每个键都是函数的名称,值是函数名的数组)。
答案 2 :(得分:1)
基本上,你不能。
除非你执行它们,否则对象/函数将不知道它们将执行什么, 除非你在函数的java脚本代码本身上执行正则表达式..最好不可靠。
如果你想倒退,追溯堆栈,这样的问题有解决方案:How can I get a Javascript stack trace when I throw an exception?
要实现您可能正在寻找的东西,您可以创建一个泛型类,您的函数将从该类继承,使用您自己的实现方法为其分配函数调用。
答案 3 :(得分:-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
的函数调用。 ..
OR
我假设您要过滤掉本机功能。在Firefox中,Function.toString()
返回函数体,对于本机函数,它将采用以下形式:
function addEventListener() {
[native code]
}
您可以匹配循环中的模式/\[native code\]/
并省略匹配的函数。