[Javascript] CommonJsモジュールシステムにおける "module.exports"と "exports"の違い


Answers

レニーの答えはよく説明されています。 例との回答に加えて:

ノードはあなたのファイルに多くのことを行い、重要なことの1つはあなたのファイルをラップしています。 ノード内のソースコード "module.exports"が返されます。 一歩踏み込んでラッパーを理解しましょう。 あなたが持っていると仮定

greet.js

var greet = function () {
   console.log('Hello World');
};

module.exports = greet;

上記のコードは、nodejsソースコードの中で次のようにIIFE(Immediately Invoked Function Expression)としてラップされます。

(function (exports, require, module, __filename, __dirname) { //add by node

      var greet = function () {
         console.log('Hello World');
      };

      module.exports = greet;

}).apply();                                                  //add by node

return module.exports;                                      //add by node

上記の関数が呼び出され(.apply())、module.exportsが返されます。 このときmodule.exportsとexportsは同じ参照を指しています。

greet.jsを次のように書き直してみましょう

exports = function () {
   console.log('Hello World');
};
console.log(exports);
console.log(module.exports);

出力は

[Function]
{}

理由は:module.exportsは空のオブジェクトです。 module.exportsには何も設定しませんでしたが、新しいgreet.jsにはexports = function().....を設定しました。 したがって、module.exportsは空です。

技術的には、輸出とmodule.exportsは同じ参照(thats正しい!)を指す必要があります。 しかし、エクスポートにfunction()....を割り当てると、メモリ内に別のオブジェクトを作成するときに "="を使用します。 したがって、module.exportsとエクスポートは異なる結果を生成します。 輸出に関しては、それを無効にすることはできません。

さて、あなたがre-write(これはMutationと呼ばれます)greet.js(Reneeの答えを参照)を

exports.a = function() {
    console.log("Hello");
}

console.log(exports);
console.log(module.exports);

出力は

{ a: [Function] }
{ a: [Function] }

あなたが見ることができるように、module.exportsとエクスポートは関数である同じ参照を指しています。 エクスポートでプロパティを設定すると、JSではオブジェクトが参照渡しされるため、module.exportsに設定されます。

結論は混乱を避けるために常にmodule.exportsを使用します。 お役に立てれば。 ハッピーコーディング:)

Question

このページ( http://docs.nodejitsu.com/articles/getting-started/what-is-require )では、「エクスポートオブジェクトを関数または新しいオブジェクトに設定するには、 module.exportsオブジェクトを使用してください。

私の質問はなぜですか?

// right
module.exports = function () {
  console.log("hello world")
}
// wrong
exports = function () {
  console.log("hello world")
}

私はconsole.logged結果( result=require(example.js) )、最初の1つは[Function]の2つ目は{}です。

あなたはそれの背後にある理由を説明していただけますか? 私はここの記事を読んでいます: node.exportsとNode.jsのエクスポート 。 それは役に立ちますが、そのように設計された理由を説明していません。 輸出の参照が直接返されても問題はありますか?




exportsmodule.exports関係についてのReneの答えは、かなり明確ですmodule.exports参照に関するものです。 ちょうどそれを追加したい:

これは多くのノードモジュールで確認できます。

var app = exports = module.exports = {};

これにより、module.exportsを変更したとしても、それらの2つの変数を同じオブジェクトを指すようにして、エクスポートを使用できることが保証されます。