Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从js文件中获取所有函数及其参数?javascript_Javascript_Node.js_Automation - Fatal编程技术网

如何从js文件中获取所有函数及其参数?javascript

如何从js文件中获取所有函数及其参数?javascript,javascript,node.js,automation,Javascript,Node.js,Automation,有一个test.js: const add = (x,y) => { return x+y; } const multiply = (x,y,z) => { return x*y*z; } 我想从index.js中读取test.js并打印它的所有函数名和参数 const fs = require("fs"); let file = fs.readFileSync("./test.js", "utf8"); let functionArg = "Do some

有一个test.js:

const add = (x,y) => {
    return x+y;
}

const multiply = (x,y,z) => {
    return x*y*z;
}
我想从index.js中读取test.js并打印它的所有函数名和参数

const fs = require("fs");

let file = fs.readFileSync("./test.js", "utf8");

let functionArg = "Do some operations"

console.log(functionArg)

//Result:
//  add : [x,y]
//  multiply : [x,y,z]
没有模块。导出。
是否可以读取js文件并返回其所有函数及其参数。

  • 读取js文件
  • const
    替换为
    this.
  • 将其包装在构造函数中并对其求值
  • 创建它的一个实例
  • 由于您将
    const
    替换为
    this.
    ,test.js中的所有变量都成为实例的成员。现在可以交互此实例以获取成员
  • 要获取函数签名,必须将函数对象转换为字符串并手动获取参数
代码如下:

const fs = require("fs");

let file = fs.readFileSync("./test.js", "utf8");

const getFuncInfo = function(file) {
  file = file.replace(new RegExp('const ', 'g'), 'this.');
  eval(`function Container(){
    ${file}}
  `)
  const instance = new Container()
  const names = Object.keys(instance)
  return names.reduce((res, cur) => {
    if(typeof instance[cur] == 'function') {
      let args = instance[cur].toString()
      res[cur] = args.split('(')[1].split(')')[0].split(',')
    }
    return res;
  }, {})
}

let functionArg = getFuncInfo(file)

console.log(functionArg)
结果是:

{ add: [ 'x', 'y' ], multiply: [ 'x', 'y', 'z' ] }
编辑: 关于
eval
做什么的问题, 如下所示:

const getFuncInfo = function(file) {
  file = file.replace(new RegExp('const ', 'g'), 'this.');
  // think like eval replace the content with below one
  function Container(){
    // content of test.js except `const ` is replaced with `this.`
    this.add = (x,y) => {
      return x+y;
    }

    this.multiply = (x,y,z) => {
      return x*y*z;
    }
  }
  // end of replacement
  const instance = new Container()
  const names = Object.keys(instance)
  return names.reduce((res, cur) => {
    if(typeof instance[cur] == 'function') {
      let args = instance[cur].toString()
      res[cur] = args.split('(')[1].split(')')[0].split(',')
    }
    return res;
  }, {})
}

我认为您已经走上了正确的道路,但您从未使用过您阅读的文件,它实际上应该是(我希望我正确地回答了您的问题):


当您需要读取代码文件时,最好是在可用时直接使用编译器

它是一个众所周知的解析器,您可能已经在不知不觉中使用了它,因为您可能正在使用babel

使用
acorn
可以将源文件解析为一个抽象的源代码树,然后通过它找到所需的内容

例如:

testfiletoparse.js


    export function factorialR(n) {
        if (n <= 1) {
            return 1;
        }
        return factorialR(n - 1) * n;
    }

    export function bound(v, min, max) {
        return Math.max(Math.min(v, min), max);
    }

    export function isNullOrEmpty(str) {
        return !str || str.length === 0;
    }

    export const arrowFunction = v => v;


    import fs from 'fs';

    const acorn = require('acorn');
    const walk = require('acorn-walk');

    require('acorn-object-rest-spread/inject')(acorn);
    require('acorn-static-class-property-initializer/inject')(acorn);
    require('acorn-class-fields/inject')(acorn);

    const filePath = 'src/testfiletoparse.js';

    const sourceCode = String(fs.readFileSync(filePath));
    const program = acorn.parse(
        sourceCode,
        {
            ranges: true,
            locations: true,
            sourceType: 'module',
            plugins: {
                objectRestSpread: true,
                // es7: true,
                staticClassPropertyInitializer: true,
                classFields: true,
            }
        }
    );

    walk.full(
        program,
        /**
         * @param {}
         */
        (node) => {
            if (node.type === 'FunctionDeclaration') {
                console.log(`There's a FunctionDeclaration node at ${JSON.stringify(node.loc.start)}`);
                console.log(`Function name is ${node.id.name}`);
                const params = node.params.map((param) => {
                    return param.name;
                }).join();
                console.log(`Function params are ${params}`);
            }
            // it is a little tricky to catch arrow functions but trial and error will get you through it
            if (node.type === 'VariableDeclarator' && node.init.type === 'ArrowFunctionExpression') {
                console.log(`There's an arrow function expression declaration node at ${JSON.stringify(node.loc.start)}`);
                console.log(`Its name is ${node.id.name}`);
                const params = node.init.params.map((param) => {
                    return param.name;
                }).join();
                console.log(`Function params are ${params}`);
            }
        }
    );

输出


    There's a FunctionDeclaration node at {"line":1,"column":7}
    Function name is factorialR
    Function params are n
    There's a FunctionDeclaration node at {"line":8,"column":7}
    Function name is bound
    Function params are v,min,max
    There's a FunctionDeclaration node at {"line":12,"column":7}
    Function name is isNullOrEmpty
    Function params are str
    There's an arrow function expression declaration node at {"line":16,"column":13}
    Its name is arrowFunction
    Function params are v


从这一点开始,找到问题的解决方案应该非常简单。

您可以在JavaScript解析器的帮助下获得函数及其参数,如


因为您不想导入函数,所以可以读取文件的每一行,并检查该行是否是函数定义或声明。如何做到这一点?对于函数,我可以读取每一行并将其拆分为一个空格,然后可以检查它是否属于函数类型。争论呢?你能解释一下你的方法吗?谢谢,您不必阅读每一行的函数。请看下面我的答案,我可以确认remix23的答案是有效的。谢谢你的回答,实际上我不想打印js文件的内容,我只想要js文件中的函数名和它们的参数。你能解释一下eval到底在做什么吗?代码正在运行。thankseval正在执行代码。看看它的参数。这不仅仅是test.js的内容。它由另一个函数包装。把它想象成编译器。
const instance=新函数(文件);这就是eval中运行的内容
。不,不是:)。请检查我编辑的答案。好的,现在我明白了,当我们放置函数Container(){file};它将file作为变量。但是当我们使用eval时,它首先用$file编写完整的函数,然后运行,感谢它的解释。出于许多原因,使用eval是一个不好的选择。谢谢分享答案。我以前听说过ESPrima,但从未使用过。在你的回答之后,我阅读了更多关于它的内容,阅读了它的代码,这有助于提高我的JS知识。@NirajKumar很好的反射。请注意,该项目在TypeScript中占68%,因此它也将有助于改进TS;)

    There's a FunctionDeclaration node at {"line":1,"column":7}
    Function name is factorialR
    Function params are n
    There's a FunctionDeclaration node at {"line":8,"column":7}
    Function name is bound
    Function params are v,min,max
    There's a FunctionDeclaration node at {"line":12,"column":7}
    Function name is isNullOrEmpty
    Function params are str
    There's an arrow function expression declaration node at {"line":16,"column":13}
    Its name is arrowFunction
    Function params are v

const fs = require("fs");
const esprima = require('esprima');

let file = fs.readFileSync("./test.js", "utf8");

let functionArg = esprima.parseScript(file);

functionArg.body.forEach(el => {
  let variableDeclarator = el.declarations[0]
  let params = []
  variableDeclarator.init.params.forEach(arg => {
    params.push(arg.name)
  })
  console.log(variableDeclarator.id.name, ' : ', [params.join()])
})

//Result:
// add  :  [ 'x,y' ]
// multiply  :  [ 'x,y,z' ]