node.js中的命名空间带有require

Mil*_*lin 8 require node.js vows

我正在玩耍并通过个人项目了解誓言.这是一个小型客户端库,在誓言中完成测试.因此,我必须构建并测试一个这样写的文件:

(function(exports) { 
    var module = export.module = { "version":"0.0.1" }; 
    //more stuff
})(this);
Run Code Online (Sandbox Code Playgroud)

在我的测试中(基于science.js,d3等)需要这样的模块:

require("../module");
Run Code Online (Sandbox Code Playgroud)

在尝试运行测试时,我继续得到"模块未定义错误",所以我去了一个repl并运行:

require("../module")
Run Code Online (Sandbox Code Playgroud)

它返回了:

{ module: { version: "0.0.1" } }
Run Code Online (Sandbox Code Playgroud)

我意识到我可以这样做:

var module = require("../module").module;
Run Code Online (Sandbox Code Playgroud)

但感觉就像我通过这种方式创建一个问题,特别是因为我基于这个项目的库是以我描述的格式进行的.

我希望我的项目行为类似于我基于它的那些项目,其中:

require("../module");
Run Code Online (Sandbox Code Playgroud)

在此命名空间中创建变量:

module.version; //is valid.
Run Code Online (Sandbox Code Playgroud)

我已经在各种库中看到了这一点,我正在遵循T的格式和思考过程,但我相信我可能会遗漏一些我不知道的需求行为.

Flo*_*ine 16

以这种方式创建它没有问题.模块定义它们在module.exports对象中返回的内容.顺便说一句,你实际上并不需要自我执行功能(SEF),没有像浏览器那样的全局泄漏:-)

例子

module1.js:

module.exports = {
    module: { 'version': '0.1.1' }
};
Run Code Online (Sandbox Code Playgroud)

main.js:

var module1 = require( './module1.js' );
// module1 has what is exported in module1.js
Run Code Online (Sandbox Code Playgroud)

一旦了解了它的工作原理,您可以立即轻松导出版本号,如果您想:

module1.js:

module.exports = '0.1.1';
Run Code Online (Sandbox Code Playgroud)

main.js:

var module1 = require( './module1.js' );
console.log( module1 === '0.1.1' ); // true
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一些逻辑,你可以module1.js像这样轻松扩展你的文件:

module.exports = ( function() {
    // some code
    return version;
} () ); // note the self executing part :-)
// since it's self executed, the exported part
// is what's returned in the SEF
Run Code Online (Sandbox Code Playgroud)

或者,正如许多模块一样,如果要导出一些实用程序功能(并保持其他功能"私有"),您可以这样做:

module.exports = {
    func1: function() {
        return someFunc();
    },

    func2: function() {},

    prop: '1.0.0'
};

// This function is local to this file, it's not exported
function someFunc() {
}
Run Code Online (Sandbox Code Playgroud)

所以,在main.js中:

var module1 = require( './module1.js' );
module1.func1(); // works
module1.func2(); // works
module1.prop; // "1.0.0"
module1.someFunc(); // Reference error, the function doesn't exist
Run Code Online (Sandbox Code Playgroud)

你的特例

关于你的特殊情况,我不建议像他们那样做.

如果你看这里:https://github.com/jasondavies/science.js/blob/master/science.v1.js

您看到他们没有使用var关键字.因此,他们正在创建一个全局变量.

这就是为什么他们可以require在定义全局变量的模块后访问它.

顺便说一句,这个exports论点在他们的案例中毫无用处.它甚至具有误导性,因为它实际上是global对象(相当于window浏览器),而不是module.exports对象(this在函数中是全局对象,undefined如果启用了严格模式则是这样).

结论

不要像他们那样做,这是一个坏主意.全局变量是一个坏主意,最好使用节点的原理,并将所需的模块存储在您重用的变量中.

如果你想拥有一个可以在客户端使用并在node.js中测试的对象,这里有一种方法:

yourModule.js:

// Use either node's export or the global object in browsers
var global = module ? module.exports : window.yourModule;

( function( exports ) {
    var yourModule = {};
    // do some stuff
    exports = yourModule;
} ( global ) );
Run Code Online (Sandbox Code Playgroud)

你可以缩短到这一点,以避免创建global变量:

( function( exports ) {
    var yourModule = {};
    // do some stuff
    exports = yourModule;
} ( module ? module.exports : window.yourModule ) );
Run Code Online (Sandbox Code Playgroud)

这样,您可以在客户端使用它:

yourModule.someMethod(); // global object, "namespace"
Run Code Online (Sandbox Code Playgroud)

在服务器端:

var yourModule = require( '../yourModule.js' );
yourModule.someMethod(); // local variable :-)
Run Code Online (Sandbox Code Playgroud)

仅供参考,..意为"父目录".这是获取模块的相对路径.如果文件位于同一目录中,则使用..