我试过看global
,但它只包含变量,不包含函数。如何列出脚本中创建的所有函数?
6 回答
使用您要查看的文件从命令行运行节点调试。然后你可以使用列表(这里有一些大数字)
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>
如果没有更高级的反射工具(如调试器),这在节点中是不可能的。
这样做的唯一方法是使用__parent__
由于安全问题和其他原因而被删除的内容。正如 Mark Bessey 所说,当您运行脚本时,这些变量将成为模块闭包变量。如果不明确导出它们,您将无法在其他地方访问它们。
这不是错误,这是设计使然。这就是节点的工作方式。但是,如果您只是要求您的用户编写函数表达式分配,那么一切都可以正常工作:
module.exports = {
a:function(){
//same logic you had in the function declaration
}
}
然后,您可以轻松地反思和枚举 module.exports 并获取所有函数名称。
如果函数有名称,它将很好地显示在全局中:
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]
如果你想做一些 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())
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 版本。
想要你正在寻找的确切的东西。找不到任何其他解决方案(大多数假设使用“window”或“this”或“global”,在 Node 中这些都不适用于我们)。
借助几个库:fs、esprima 和 escodegen,我们可以用大约 25 行代码完成。
const fs = require('fs');
const esprima = require("esprima");
const escodegen = require("escodegen");
逻辑是这样的:
- 让我们获取这个函数所在的文件,首先将它作为文本读取,就像我们将读取为纯文本的任何其他文件一样
- 我们将使用 esprima 将该文本解析为一个有效的树,其中一部分将包含我们的函数
- 我们将过滤掉该树以仅包含函数(除了我们用来执行此操作的此函数!我们不在之后)
- 为此,我们需要获取简单的函数声明
- 但理想情况下,我们也可以使用箭头表达式获取任何声明为变量的函数,这需要更多的工作,但非常可行。
- 接下来,我们希望将这些对象从树中重建回代码中实际可用的函数,因此对于我们所有的函数:
- 使用 escodegen 将该对象重建为一个字符串,该字符串看起来就像为该函数编写的代码
- 再次将该字符串转换为脚本本身内的可用函数
最终结果将返回一个带有键:值对的对象,其中键是函数名称的字符串,值是函数本身。
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;
}