我想获得用Javascript代码制作的所有函数和变量声明。 我使用esprima,我想知道是否可以使用脚本实现我的目标?
例如,我们有以下代码:
var myVar1;
var myVar2;
function myTestFunction(funcVar1, funcVar2) {
var myVar3;
}
我除了:
带有变量的数组
["myVar1", "myVar2"]
还有一个带有函数的数组:
[{"name": "myTestFuncttion", "params":["funcVar1", "funcVar2"], "variables": ["myVar3"]}]
任何想法如何实现这一目标?
答案 0 :(得分:0)
用小提琴完成解决方案:
以下是一些JavaScript代码用于测试运行:
var hello = 41;
function aaaaa(p1, p2, p3){
var a1 = 7, a2 = 8;
var a3 = 9;
function bbbbb(q1, q2){
var b1 = 10, b2 = 11;
return 12;
}
var a4 = 99;
function ccccc(r1, r2, r3){
var c1 = 13;
var c2 = 14;
var c3 = 15, c4 = 16;
return 17;
}
var a5 = 88, a6 = 77;
function ddddd(s1){
return s1 === 18
? function (x){ return x+1; }
: function (y){ return 22; }
}
return p1 + a3 <= 42 ? 55 : ccc(p1, 0, 0);
}
var world = 42;
function xxxxx(x){
var z=0;
return 0;
}
我假设这是所需的输出:
{
"vars": ["hello", "world" ],
"funcs": [
{
"name": "aaaaa",
"params": ["p1", "p2", "p3"],
"variables": ["a1","a2","a3","a4","a5","a6"]
},
{
"name": "bbbbb",
"params": ["q1","q2"],
"variables": ["b1","b2"]
},
{
"name": "ccccc",
"params": ["r1","r2","r3"],
"variables": ["c1","c2","c3","c4"]
},
{
"name": "ddddd",
"params": ["s1"],
"variables": []
},
{
"name": "xxxxx",
"params": ["x"],
"variables": ["z"]
}
]
}
列表是平坦的,并且ddddd中的匿名函数将被忽略(它们是FunctionExpressions而不是FunctionDeclarations)。猜测这就是您想要的。
这是代码-可能/希望在无需进一步说明的情况下易于理解:
function findDeclarations(code){
var ast = esprima.parse(code);
var funcDecls = [];
var globalVarDecls = [];
var funcStack = [];
function visitEachAstNode(root, enter, leave){
function visit(node){
function isSubNode(key){
var child = node[key];
if (child===null) return false;
var ty = typeof child;
if (ty!=='object') return false;
if (child.constructor===Array) return ( key!=='range' );
if (key==='loc') return false;
if ('type' in child){
if (child.type in esprima.Syntax) return true;
debugger; throw new Error('unexpected');
} else { return false; }
}
enter(node);
var keys = Object.keys(node);
var subNodeKeys = keys.filter(isSubNode);
for (var i=0; i<subNodeKeys.length; i++){
var key = subNodeKeys[i];
visit(node[key]);
}
leave(node);
}
visit(root);
}
function myEnter(node){
if (node.type==='FunctionDeclaration') {
var current = {
name : node.id.name,
params : node.params.map(function(p){return p.name;}),
variables : []
}
funcDecls.push(current);
funcStack.push(current);
}
if (node.type==='VariableDeclaration'){
var foundVarNames = node.declarations.map(function(d){ return d.id.name; });
if (funcStack.length===0){
globalVarDecls = globalVarDecls.concat(foundVarNames);
} else {
var onTopOfStack = funcStack[funcStack.length-1];
onTopOfStack.variables = onTopOfStack.variables.concat(foundVarNames);
}
}
}
function myLeave(node){
if (node.type==='FunctionDeclaration') {
funcStack.pop();
}
}
visitEachAstNode(ast, myEnter, myLeave);
return {
vars : globalVarDecls,
funcs : funcDecls
};
}
要进行测试,您可以输入
JSON.stringify(
findDeclarations(
'var hello=41;\n' +
aaaaa.toString() +
'var world=42;\n' +
xxxxx.toString()
),
null, 4
)
您还可以使用estraverse软件包,该软件包可在github上找到。然后,本质上,应该用estraverse.traverse替换功能visitEachAstNode,否则您可以保留代码不变。