315

このページ ( 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)、最初のものは[Function]2 番目のものは{}です。

その理由を教えてください。ここで投稿を読みました: module.exports vs exports in Node.js。役に立ちますが、そのように設計されている理由を説明していません。exports の参照が直接返された場合、問題はありますか?

4

8 に答える 8

697

moduleexportsプロパティを持つプレーンな JavaScript オブジェクトです。exportsに設定されている単純な JavaScript 変数ですmodule.exportsmodule.exportsファイルの最後で、node.js は基本的に関数に「戻ります」require。Node で JS ファイルを表示する簡単な方法は次のとおりです。

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

// your code

return module.exports;

exportsのようににプロパティを設定すると、JavaScript ではオブジェクトが参照として渡されるためexports.a = 9;、それも設定さmodule.exports.aれます。つまり、複数の変数を同じオブジェクトに設定すると、それらすべて同じオブジェクトになります。exportsとはmodule.exports同じオブジェクトです。
しかし、exports何か新しいものを設定すると、 に設定されmodule.exportsなくなり、exportsmodule.exportsは同じオブジェクトではなくなります。

于 2013-05-05T11:15:41.677 に答える
71

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

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

あいさつ.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 には何も設定せず、newgreet.js で exports = function()..... を設定しました。したがって、module.exports は空です。

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

ここで、(これはミューテーションと呼ばれます)greet.js(レニーの回答を参照)を次のように書き直したとします。

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

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

出力は次のようになります

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

ご覧のとおり、module.exports と exports は関数である同じ参照を指しています。exports にプロパティを設定すると、module.exports に設定されます。これは、JS ではオブジェクトが参照渡しであるためです。

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

于 2017-01-06T02:56:25.377 に答える
29

また、理解に役立つ可能性のあることの1つ:

math.js

this.add = function (a, b) {
    return a + b;
};

client.js

var math = require('./math');
console.log(math.add(2,2); // 4;

すばらしい、この場合:

console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true

したがって、デフォルトでは、「this」は実際には module.exports と同じです。

ただし、実装を次のように変更した場合:

math.js

var add = function (a, b) {
    return a + b;
};

module.exports = {
    add: add
};

この場合、問題なく動作しますが、新しいオブジェクトが作成されたため、"this" は module.exports と等しくなくなりました。

console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false

そして今、require によって返されるのは、これやエクスポートではなく、module.exports 内で定義されたものです。

それを行う別の方法は次のとおりです。

math.js

module.exports.add = function (a, b) {
    return a + b;
};

または:

math.js

exports.add = function (a, b) {
    return a + b;
};
于 2016-03-25T13:42:39.667 に答える
16

exportsとの関係に関するルネの答えmodule.exportsは非常に明確です。それはすべてJavaScriptの参照に関するものです。それを追加したいだけです:

これは、多くのノード モジュールで見られます。

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

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

于 2014-10-02T15:09:16.467 に答える