我尝试查看global
,但它只包含变量而不是函数。我如何列出在我的脚本中创建的所有函数?
我尝试查看global
,但它只包含变量而不是函数。我如何列出在我的脚本中创建的所有函数?
在命令行中使用node debug命令并指定要查看的文件。然后,您可以使用list(此处填写一个大数字)命令。
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>
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]
如果没有像debugger这样更高级的反射工具,那么在Node中实现这一点是不可能的。
唯一的方法是使用__parent__
,但由于安全问题和其他原因,该方法已被移除。正如Mark Bessey所说,当您运行脚本时,这些变量成为模块闭包变量。您不能在其他地方访问它们,除非显式地导出它们。
这不是一个错误,而是设计上的考虑。这就是Node的工作方式。然而,如果您要求用户编写函数表达式赋值,那么一切都会正常工作:
module.exports = {
a:function(){
//same logic you had in the function declaration
}
}
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");
最终结果将返回一个对象,其中键值对的键是函数名称的字符串,而值是函数本身。
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;
}
如果你想做一些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())