express
のNodeJS
フレームワークのランダムな ソースファイル を見ると、理解できないコードが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
?
具体的には:
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 +とmodule
はnot同じです。 (ブラウザでは、グローバルスコープコンテキストと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
Raynosの答えを拡大するには...
exports
は、基本的にはmodule.exports
のaliasです。使用しないことをお勧めします。 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.exports
とrequire
を使用して遊ぶ方法は他にもたくさんあります。覚えておいてください、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
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を変更しないように注意してください。そうしないと、現在のエクスポートは無意味になります。
moduleは、その特定のソースファイルが公開するものを表すオブジェクトです。 c/c ++の世界でヘッダーファイルに似たものを用意する代わりに、このオブジェクトを定義することで、モジュールexportsを記述します。ノードランタイムはこのオブジェクトを使用して、モジュールが「パブリック」であるかどうかを判断します。
コンパイルされた世界でdllから関数をエクスポートするのと同様の概念。外部の世界からアクセスできる機能を明示的に定義する必要があります。これはカプセル化に役立ち、クリーンな方法でライブラリを整理できます。
モジュールのコードは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;