在Node.js中,如果我加载一个包含模块范围内代码的模块,如:
this["foo"] = function() { console.log("foo"); }
...然后我似乎得到了一个全局可用的函数,我可以通过使用该模块从任何代码中说出foo()
来调用它。它可以被视为Object.getOwnPropertyNames(this)
的打印项目之一。
但是,如果我将以下内容放在模块范围内:
function foo() { console.log("foo"); }
...然后它产生一个函数,可以在该模块中类似地调用foo()
,但在它之外是不可见的(例如,不会显示为Object.getOwnPropertyNames(this)
的项目之一)
我认为这是对浏览器中所做的运行时行为的改变。浏览器似乎默认将所有内容都放到全局范围内(多年来人们必须通过在匿名函数/等中包装来有意识地避免这种情况。)
我的问题是NodeJs是否有一些秘密的方式与模块之外的这些声明进行交互,在模块中使用exports.(...) = (...)
声明它们 BESIDES。是否可以以某种方式枚举它们,或者如果它们未被模块导出调用,它们是否会被声明为垃圾收集?如果我知道在加载模块之前这个函数的名称是什么......我可以告诉Node.js在定义它时“捕获它”吗?
我不希望任何此类功能得到充分记录......但可能还有调试器功能或其他系统调用。最好的指针之一是Node.js项目中处理此类声明的特定代码,以查看是否存在漏洞。
注意:在研究V8时,我发现“函数定义”没有被添加到上下文中。它被放入“执行上下文”的“激活对象”中,无法以编程方式访问。如果你想要一些“轻读”,我发现:
答案 0 :(得分:2)
如果你填写exports.foo = foo;假设您使用文件名执行var myFile = require('myFile.js')并通过myFile.foo()调用该函数;在文件末尾它将在节点中的其他文件中可用。您甚至可以在导出时重命名该函数以供外部使用,并在使用require时设置您想要调用该包的任何内容。
顺便说一句,你可以枚举这些函数,就像你在任何JSON对象上一样(即对于k in ...)
答案 1 :(得分:1)
如果没有像调试器这样的更高级的反射工具,这在节点中是不可能的。
执行此操作的唯一方法是使用由于安全问题和其他因素而删除的__parent__
(难以优化,而不是开始时的标准)。运行脚本时,这些变量将在模块下关闭。如果没有明确导出它们,您就无法在其他地方访问它们。
这不是一个错误,它是设计的。这就是节点的工作原理。 see this closely related question。
如果没有像调试器这样的工具可以使用这种反射,那么非常很难优化源代码(至少v8的工作方式),这意味着你的问题的答案是否定的。遗憾。