6

我试过看global,但它只包含变量,不包含函数。如何列出脚本中创建的所有函数?

4

6 回答 6

5

使用您要查看的文件从命令行运行节点调试。然后你可以使用列表(这里有一些大数字)

node debug mini_file_server.js 
< debugger listening on port 5858
connecting... ok
debug> scripts
  26: mini_file_server.js
debug> list(1000)
  1 var http = require('http'),
  2     util = require('util'),
  3     fs   = require('fs');
  4 
  5 server = http.createServer(function(req, res){  
  6     var stream  = fs.createReadStream('one.html'),
  7         stream2 = fs.createReadStream('two.html');
  8     console.log(stream);
  9     console.log(stream2);
 10     stream.on('end', function(){
 11         stream2.pipe(res, { end:false});
 12     });
 13 
 14     stream2.on('end', function(){
 15         res.end("Thats all!");
 16     });
 17 
 18     res.writeHead(200, {'Content-Type' : 'text/plain'});
 19     stream.pipe(res, { end:false});
 20     stream2.pipe(res, { end:true});
 21 
 22 }).listen(8001);
 23 });
debug> 
于 2012-05-05T20:03:32.257 回答
3

如果没有更高级的反射工具(如调试器),这在节点中是不可能的。

这样做的唯一方法是使用__parent__由于安全问题和其他原因而被删除的内容。正如 Mark Bessey 所说,当您运行脚本时,这些变量将成为模块闭包变量。如果不明确导出它们,您将无法在其他地方访问它们。

这不是错误,这是设计使然。这就是节点的工作方式。但是,如果您只是要求您的用户编写函数表达式分配,那么一切都可以正常工作:

module.exports = {
    a:function(){
        //same logic you had in the function declaration
    }
}

然后,您可以轻松地反思和枚举 module.exports 并获取所有函数名称。

于 2013-04-01T09:38:04.400 回答
3

如果函数有名称,它将很好地显示在全局中:

mb-work-laptop:~ markbessey$ node
> for (var k in global) { console.log(k); }
global
process
GLOBAL
root
Buffer
setTimeout
setInterval
clearTimeout
clearInterval
console
module
require
k
> function z(a) { return a*10; }
> for (var k in global) { console.log(k); }
global
process
GLOBAL
root
Buffer
setTimeout
setInterval
clearTimeout
clearInterval
console
module
require
k
z
> 
> global.z
[Function: z]
于 2012-05-06T01:41:03.960 回答
0

如果你想做一些 AOP,路线是 AST。

您可以使用以下内容构建您自己的 AOP 框架:http: //esprima.org

或者您可以尝试node-burrito,非常适合不那么复杂的方面:

var burrito = require('burrito');

var src = burrito('someCall()', function (node) {
    if (node.name === 'call') node.wrap('qqq(%s)');
});

会产生

qqq(somecall())
于 2013-04-01T09:12:11.677 回答
0

cli:http ://nodejs.org/docs/v0.3.7/api/debugger.html

gui: https://github.com/dannycoates/node-inspector

还有https://github.com/c4milo/node-webkit-agent正在开发中,这将是一个更强大的 node-inspector 版本。

于 2012-05-05T19:55:44.500 回答
0

想要你正在寻找的确切的东西。找不到任何其他解决方案(大多数假设使用“window”或“this”或“global”,在 Node 中这些都不适用于我们)。

借助几个库:fs、esprima 和 escodegen,我们可以用大约 25 行代码完成。

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

逻辑是这样的:

  1. 让我们获取这个函数所在的文件,首先将它作为文本读取,就像我们将读取为纯文本的任何其他文件一样
  2. 我们将使用 esprima 将该文本解析为一个有效的树,其中一部分将包含我们的函数
  3. 我们将过滤掉该树以仅包含函数(除了我们用来执行此操作的此函数!我们不在之后)
  4. 为此,我们需要获取简单的函数声明
  5. 但理想情况下,我们也可以使用箭头表达式获取任何声明为变量的函数,这需要更多的工作,但非常可行。
  6. 接下来,我们希望将这些对象从树中重建回代码中实际可用的函数,因此对于我们所有的函数:
  7. 使用 escodegen 将该对象重建为一个字符串,该字符串看起来就像为该函数编写的代码
  8. 再次将该字符串转换为脚本本身内的可用函数

最终结果将返回一个带有键:值对的对象,其中键是函数名称的字符串,值是函数本身。

function getAllFunctionsInThisFileExceptThisFunction() {
    const thisFunctionName = arguments.callee.name;
    const rawTextFromThisFile = fs.readFileSync(__filename, "utf8");
    const parsed = esprima.parseScript(rawTextFromThisFile);
    const allDeclaredVariables = parsed.body.filter(e=>e.type === "VariableDeclaration");
    const allDeclaredFunctions = parsed.body.filter(e=>e.type === "FunctionDeclaration");
   
    let allFunctions = []
    for (declaredVariable of allDeclaredVariables){ 
        const declarations = declaredVariable.declarations[0];
        if (declarations.init.type === "ArrowFunctionExpression"){ 
            const anonymousFunction = declarations.init;
            let reconstructedFunction = anonymousFunction;
            reconstructedFunction.id = declarations.id;
            allFunctions.push(reconstructedFunction);
        }
    }
    allFunctions.push(...allDeclaredFunctions)

    const allFunctionsExceptThisOne = allFunctions.filter(e => e.id.name !== thisFunctionName);
    let functionsDict = {};
    for (parsedFunction of allFunctionsExceptThisOne) {
        const functionString = escodegen.generate(parsedFunction);
        const newFunction = eval(`(${functionString})`)
        functionsDict[parsedFunction.id.name] = newFunction;
    }
    return functionsDict;
}

从那里你可以像任何其他对象/字典一样玩弄它。

const allFunctionsDict = getAllFunctionsInThisFileExceptThisFunction();
console.log( allFunctionsDict["sum"](10,30) ) //prints 40
console.log( allFunctionsDict["difference"](350,250) ) //prints 100
console.log( allFunctionsDict["product"](6,4) ) // prints 24
console.log( Object.keys(allFunctionsDict) ) //prints [ 'product', 'sum', 'difference' ]

function sum(a, b) {
    return a + b;
}

function difference(a, b) {
    return a - b;
}

const product = (a,b) => { 
    return a * b;
}
于 2022-01-05T20:37:15.660 回答