Posted at

もっと簡単に exports と module.exports の違い

More than 1 year has passed since last update.


1. 使い分け



  • exports は const だと思った方が良い (常に exports.hoge = fuga; の形で使う)


  • module.exports は自由

  • モジュール内で併用しない

これらの条件を守っていれば、どちらを使っても同じ。

class をまるっと入れたいときは module.exports になる。


2. 仕組み


イメージ

let a = {}; /* module.exports */

let b = a; /* exports */
//
b.foo = 'foo';
//
a = {bar: 'bar'}
//
return a;



  • b に新しいオブジェクトを入れても反映されない


  • a に新しいオブジェクトを入れると b が無視される

  • どちらも新しいオブジェクトを入れなければ両方反映 (でも、統一したほうが見やすい)

参考「exports と module.exports の違い - Qiita

参考「Node.js : exports と module.exports の違い(解説編) - ぼちぼち日記


3. 循環参照の対策

以下のいずれか。



  • module.exports の参照を破壊しないで使う


  • exports を使う ( = 参照を破壊しない)


  • module.exports の参照を require() 前に書き換える

  • ソースコードの先頭ではなく使うときに require()

  • 「依存性の注入 (Dependency injection)」

参考「exports と module.exportsの使い分け - Qiita

参考「webpackなどでCommonJSモジュール循環参照を回避する方法 - Qiita

参考「node.jsにおける循環参照に対処するための3つの方法 - Qiita


4. おまけ

exports だけでなく module も似た感じなので、オブジェクトをまるっと入れるとまずい。

(module = {exports: {hoge: fuga}}; は意味がない)


require() 疑似コード

function require(/* ... */) {

const module = { exports: {} };
((module, exports) => {
// ... モジュールのコード
})(module, module.exports);
return module.exports;
}

参考「exports shortcut - Modules | Node.js v9.6.1 Documentation