Node.js

exports と module.exportsの使い分け

More than 3 years have passed since last update.


exports


  • 多数の関数やオブジェクト(定数とか)を返す時に使いやすい

  • 循環参照しているモジュール構成でも問題ない


想定される使い方

var hoge = require('./hoge');

var h = new hoge.Hoge(hoge.SPEC.FUGA);

var x = hoge.util(h);



module.exports


  • 単一のクラスや単一の関数を返す時に使いやすい

  • 循環参照しているモジュール構成の時に問題がおきる

  • 自プロジェクト内で依存関係が少ない場合に向いている(npmで取ってきたモジュール以外はrequireしないほうがいい)


想定される使い方

var Hoge = require('./hoge');

var hoge = new Hoge();


循環参照のケース

以下のようなケースにおいてmodule.exportsを使ってモジュールを外部に出すと問題が起きる


main.js

var TestManager = require('./test_manager');

var test = TestManager.instance.create()
test.ok()



test.js

var TestManager = require('./test_manager');

var Test = module.exports = function(){
this.initialize();
}
Test.prototype.initialize = function(){
TestManager.instance.add(this);
}
Test.prototype.ok = function(){
console.log("ok");
}
Test.prototype.dispose = function(){
TestManager.instance.remove(this);
}



test_manager.js

var Test = require('./test');

var TestManager = function(){
this.tests = [];
}
TestManager.prototype.create = function(){
return new Test();
}

TestManager.prototype.add = function(test){
this.tests.push(test);
}
TestManager.prototype.remove = function(test){
this.tests = this.tests.filter(function(v){ return v !== test });
}

module.exports = {
instance : new TestManager()
}



console

$ node main.js 

c:\Users\you2\x\test.js:7
TestManager.instance.add(this);
^
TypeError: Cannot read property 'add' of undefined
at Test.initialize (c:\Users\you2\x\test.js:7:25)
at new module.exports (c:\Users\you2\x\test.js:4:10)
at TestManager.create (c:\Users\you2\x\test_manager.js:7:12)
at Object.<anonymous> (c:\Users\you2\x\main.js:4:33)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)