NodeJS函数/模块包含范围
我正在开发一个应用程序与node.js和socket.io。 我已经在一个连接特定的块中build立了一个包含一些variables和函数的小规模项目。 这些函数可以访问在该块中声明的variables,而不需要特别地传递值。
这工作正常,并可以接受这个规模的项目。 但是,当我试图清理代码时,我考虑将这些函数分解到它们自己的文件中,并使用exports.functionname来声明模块,如下所述: http : //nodejs.org/docs/v0。 3.2 / API / modules.html
但是,这些函数在require()'d in而不是实际在文件中声明时通常不会访问同一块中的variables。
有什么方法可以使外部文件中的函数像在nodejs中本地声明一样吗?
有没有黑客模块系统,这正是我所做的。 https://github.com/Benvie/Node.js-Ultra-REPL/blob/master/lib/ScopedModule.js
我不能说我推荐它用于生产。 基本上这个问题更多的是JavaScript本身。 节点将模块封装在一个函数中,以便它们拥有自己的专用范围。 在该范围内共享的唯一方式是在该function内部执行,这对于模块(模块化…)系统来说并不真正起作用。 唯一的其他范围是全球性的也是不可取的。
我用来解决这个问题的技巧是改变包装函数的基础上的dynamic属性的外部定义的模块导入,以便从模块包装内所有这些参数看起来像他们神奇的定义,但不是全球性的。
节点的模块包装看起来像这样:
(function (exports, module, require, __filename, __dirname){ /**module**/ })
我的地方只是添加更多的参数,并确保在执行模块包装之前解决它们。
我已经在加载模块之前在给定的文件夹中读取名为“.deps.json”的文件。 一个例子就是这样
[{ "providers": [ "./utility/", "./settings/" ], "receivers": [ "*" ] }]
因此,它将加载这些子文件夹中的模块,然后将每个模块公开为封装器中的一个参数,并以文件名命名。
通常的干净的方法是在模块中定义一个函数,它将所需的variables作为参数:
// extracted_file.js exports.handler = function(param1, param2) { return param1 + param2; } // caller file var extractedHandler = require('./extracted_file').handle; var localVar1 = 1300, localVar2 = 37; console.log(extractedHandler(localVar1, localVar2));
您可以使用toString()
和可怕的eval
来更改函数作用域。
如果你的函数在说lib.js如下:
var lib = {} lib.foo = function() { console.log(var1) } lib.bar = function() { console.log(var2) } module.exports = lib
在main.js中你可以有这个:
var var1 = 1 var var2 = 2 var ob1 = require('./lib') ob1.foo() ob1.bar()
当你运行它ob1.foo()行给出一个ReferenceError,var1没有定义。 这是因为foo()的作用域来自lib.js而不是你的主js文件,而var1对它来说是不可见的。 ob1.foo是对lib.js作用域的函数的引用。 您需要使用main.js作用域进行新的引用。
要做到这一点每个函数转换为string和评估它。 这将创build一个具有相同代码但main.js作用域的新函数。 下面是使用setMainScope方法的一种方法,它循环遍历所有将其作用域改为main.js的函数。
var var1 = 1 var var2 = 2 var ob1 = {} ob1.setMainScope = function(ob2) { for(var prop in ob2) { if( !ob2.hasOwnProperty(prop) ) {continue} if( typeof ob2[prop] !== 'function' ) {continue} this[prop] = eval( "(" + ob2[prop].toString() + ")" ) } } ob1.setMainScope( require('./lib') ) ob1.foo() // 1 ob1.bar() // 2
现在除了使用eval
以外,它都可以正常工作。 foo()
和bar()
的作用域现在是main.js,所以它们看到了var1
和var2
。