web-dev-qa-db-ja.com

NodeJS / Expressで「module.exports」と「exports.methods」はどういう意味ですか?

expressNodeJSフレームワークのランダムな ソースファイル を見ると、理解できないコードが2行あります(これらのコード行はほとんどすべてのNodeJSファイル)。

/**
 * Expose `Router` constructor.
 */

exports = module.exports = Router;

そして

/**
 * Expose HTTP methods.
 */

var methods = exports.methods = require('./methods');

最初のコードにより、ファイル内の残りの関数がNodeJSアプリに公開されることを理解しています、しかし、私は正確に理解していませんそれがどのように機能するか、または行のコードが何を意味するか。

exportsおよびmodule.exports実際に意味ですか?

2番目のコードでは、ファイル内の関数がmethodsにアクセスできますが、これはどのように正確に行われますか。

基本的に、これらの魔法の言葉は何ですか:moduleおよびexports

56
mrwooster

具体的には:

moduleは、ファイル内のグローバルスコープ変数です。

したがって、require("foo")を呼び出す場合:

// foo.js
console.log(this === module); // true

windowがブラウザで動作するのと同じように動作します。

globalという別のグローバルオブジェクトもあります。これは任意のファイルで読み書きできますが、グローバルスコープを変更する必要があり、これは[〜#〜] evilです[〜#〜]

exportsは、module.exportsに存在する変数です。基本的には、ファイルが必要なときにexportするものです。

// foo.js
module.exports = 42;

// main.js
console.log(require("foo") === 42); // true

exports自体には小さな問題があります。 _global scope context +とmodulenot同じです。 (ブラウザでは、グローバルスコープコンテキストとwindowは同じです)。

// foo.js
var exports = {}; // creates a new local variable called exports, and conflicts with

// living on module.exports
exports = {}; // does the same as above
module.exports = {}; // just works because its the "correct" exports

// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works

エクスポートの詳細を読む

79
Raynos

Raynosの答えを拡大するには...

exportsは、基本的にはmodule.exportsaliasです。使用しないことをお勧めします。 module.exportsで設定することにより、モジュールからメソッドとプロパティを公開できます。

//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5

次に、コードでアクセスします。

var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)

overridemodule.exportsを使用して、必要に応じて単一のオブジェクトを提供することもできます。

//glorp.js
module.exports = function () {
  this.foo = function () { return 'bar' }
  this.baz = 5
  return this // need to return `this` object here
}

これで、ニースのプロトタイプができました。

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)

module.exportsrequireを使用して遊ぶ方法は他にもたくさんあります。覚えておいてください、require('foo')複数回呼び出しても常に同じインスタンスを返します

注意

以下が機能するために、

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz) 

thisは、module.exportsに割り当てられた関数で返す必要があります。それ以外の場合は、TypeErrorを取得します。

console.log(g1.foo())
          ^
TypeError: Cannot read property 'foo' of undefined
34
Tamzin Blake

Node.jsのソースコードでベストアンサーを見つけることができます。誰かがあなたのjsモジュールを要求している場合、スクリプトは次のようにノードごとの関数になります(src/node.jsを参照)。

// require function does this..
(function (exports, require, module, __filename, __dirname) {
    ... your javascript contents...
});

Nodeはスクリプトをラップします。その後、上記のスクリプトは次のように実行されます。

//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

スクリプトで、

exports is just module.exports.

スクリプトで、このエクスポートオブジェクト(関数..)に何かを追加できます。 require関数はこのオブジェクトを返します。これは、node.jsのモジュールシステム(commonJS仕様)です。

ただし、module.exportsを変更しないように注意してください。そうしないと、現在のエクスポートは無意味になります。

15
jeremyko

moduleは、その特定のソースファイルが公開するものを表すオブジェクトです。 c/c ++の世界でヘッダーファイルに似たものを用意する代わりに、このオブジェクトを定義することで、モジュールexportsを記述します。ノードランタイムはこのオブジェクトを使用して、モジュールが「パブリック」であるかどうかを判断します。

コンパイルされた世界でdllから関数をエクスポートするのと同様の概念。外部の世界からアクセスできる機能を明示的に定義する必要があります。これはカプセル化に役立ち、クリーンな方法でライブラリを整理できます。

1
Josh

モジュールのコードはmodule.exports(おそらく、他のモジュールで構成されたモジュール)にラップされています。モジュールを構築するには多くの方法がありますが、これは非常に一般的なものです(そして私の個人的なお気に入り)。

// Dependencies
// const module = require('module');

// Module object
var foo = {}

// Internal property
foo._a = 'a';

// "Public" property
foo.b = 'b';

// Method
foo.fu = function() { return 'fu' };

// Export
module.exports = foo;