首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Esprima get函数和变量声明

Esprima get函数和变量声明
EN

Stack Overflow用户
提问于 2019-09-10 16:17:44
回答 1查看 560关注 0票数 0

我想在Javascript代码中获得所有的函数和变量声明。我使用esprima,我想知道是否有脚本可以用来实现我的目标?

例如,我们有这样的代码:

代码语言:javascript
复制
var myVar1;
var myVar2;
function myTestFunction(funcVar1, funcVar2) {
  var myVar3; 
}

我不知道的是:

带变量的数组

代码语言:javascript
复制
["myVar1", "myVar2"]

和一个带有函数的数组:

代码语言:javascript
复制
[{"name": "myTestFuncttion", "params":["funcVar1", "funcVar2"], "variables": ["myVar3"]}]

有什么办法可以做到这一点吗?

EN

回答 1

Stack Overflow用户

发布于 2019-11-07 20:14:30

带小提琴的完整解决方案:

下面是一些用于测试运行的JavaScript代码:

代码语言: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;
}

我假设这是所需的输出:

代码语言:javascript
复制
{
    "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"]
        }
    ]
}

列表是扁平的,并且and中的匿名函数被忽略(它们是FunctionExpressions而不是FunctionDeclarations)。猜想这就是你想要的。

以下是代码-可能/希望很容易理解,不需要更多的解释:

代码语言:javascript
复制
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
    };
}

为了进行测试,您可以输入

代码语言:javascript
复制
JSON.stringify(
    findDeclarations(
        'var hello=41;\n' +
        aaaaa.toString() +
        'var world=42;\n' +
        xxxxx.toString()
    ),
    null, 4
)

你也可以使用estraverse包,它可以在github上找到。然后,从本质上讲,应该用estraverse.traverse替换函数visitEachAstNode,否则您可以保持代码不变。

fiddle

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57866663

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档