Node.js モジュールで次のコントラクトを見つけました。
module.exports = exports = nano = function database_module(cfg) {...}
module.exports
ここでととの違いは何なのだろうかexports
。
Node.js モジュールで次のコントラクトを見つけました。
module.exports = exports = nano = function database_module(cfg) {...}
module.exports
ここでととの違いは何なのだろうかexports
。
設定module.exports
すると、database_module
関数を関数のように呼び出すことができますrequired
。ノードがオブジェクト参照exports
をエクスポートするため、設定するだけでは関数をエクスポートできません。module.exports
次のコードでは、ユーザーが関数を呼び出すことはできません。
以下は動作しません。
exports = nano = function database_module(cfg) {return;}
が設定されている場合、以下が機能module.exports
します。
module.exports = exports = nano = function database_module(cfg) {return;}
コンソール
var func = require('./module.js');
// the following line will **work** with module.exports
func();
基本的に、 node.jsは現在参照しているオブジェクトをエクスポートしませんexports
が、最初に参照しているオブジェクトのプロパティをエクスポートしますexports
。Node.jsはオブジェクト参照をエクスポートしますがmodule.exports
、関数のように呼び出すことができます。
それらは両方module.exports
を設定し、以前にエクスポートされたオブジェクトを参照していないexports
ことを確認します。exports
両方を設定することexports
で、省略形として使用し、後で潜在的なバグを回避できます。
exports.prop = true
代わりに使用すると、module.exports.prop = true
文字が保存され、混乱を避けることができます。
require
基本的に、答えは、モジュールがステートメントを介して要求されたときに実際に何が起こるかにあります。モジュールが必要になるのはこれが初めてであると仮定します。
例えば:
var x = require('file1.js');
file1.js の内容:
module.exports = '123';
上記のステートメントが実行されると、Module
オブジェクトが作成されます。そのコンストラクタ関数は次のとおりです。
function Module(id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
if (parent && parent.children) {
parent.children.push(this);
}
this.filename = null;
this.loaded = false;
this.children = [];
}
ご覧のとおり、各モジュール オブジェクトには name のプロパティがありますexports
。これは、最終的に の一部として返されるものですrequire
。
require の次のステップは、file1.js の内容を以下のような無名関数にラップすることです。
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
});
そして、この匿名関数は次の方法で呼び出されます。module
ここでは、Module
以前に作成されたオブジェクトを参照します。
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");
関数内でわかるように、exports
仮引数は を参照しmodule.exports
ます。本質的に、これはモジュール プログラマーに提供される利便性です。
ただし、この便利さには注意が必要です。いずれにせよ、新しいオブジェクトをエクスポートに割り当てようとする場合は、必ずこの方法で行ってください。
exports = module.exports = {};
間違った方法に従ってそれを行うとmodule.exports
、モジュールインスタンスの一部として作成されたオブジェクトを指し続けます。
exports = {};
その結果、上記の exports オブジェクトに何かを追加しても、module.exports オブジェクトには影響せず、require の一部として何もエクスポートまたは返されません。
最初は、module.exports=exports
であり、require
関数はオブジェクトがmodule.exports
参照するものを返します。
たとえば、オブジェクトにプロパティを追加するとexports.a=1
、module.exports と exports は引き続き同じオブジェクトを参照します。したがって、require を呼び出してモジュールを変数に割り当てると、変数にはプロパティ a があり、その値は 1 です。
しかし、たとえば、それらの 1 つをオーバーライドexports=function(){}
すると、それらは異なります。exports は新しいオブジェクトを参照し、module.exports は元のオブジェクトを参照します。また、ファイルが必要な場合、module.exports は新しいオブジェクトを参照していないため、新しいオブジェクトは返されません。
私にとっては、新しいプロパティを追加し続けるか、両方を新しいオブジェクトにオーバーライドします。1つをオーバーライドするだけでは正しくありません。module.exports
そして、それが本当の上司であることを覚えておいてください。
JavaScript でオブジェクトが参照によって渡される方法とは微妙な違いです。
exports
どちらも同じオブジェクトをmodule.exports
指しています。exports
変数でmodule.exports
あり、モジュール オブジェクトの属性です。
次のように書いたとします。
exports = {a:1};
module.exports = {b:12};
exports
そしてmodule.exports
今、別のオブジェクトを指しています。エクスポートを変更しても、module.exports は変更されなくなりました。
インポート機能が検査module.exports
すると、それが取得されます{b:12}
これは、マニングの出版物からのアクションブックのnode.jsのノードモジュールについて書かれた良い説明です。
アプリケーションで最終的にエクスポートされるのは、module.exports です。exportsは、最初はプロパティを追加できる空のオブジェクトとして定義されているmodule.exportsへのグローバル参照として単純に設定されます。したがって、exports.myFuncはmodule.exports.myFuncの省略形です。
その結果、exportsが他の値に設定されている場合、 module.exportsとexportsの間
の参照が壊れます。module.exports のため
が実際にエクスポートされるものであり、エクスポートは期待どおりに機能しなくなります —モジュール .exportsを参照しなくなります。そのリンクを維持したい場合は、次のようにmodule.exports
参照エクスポートを再度作成できます。
module.exports = exports = db;
私はいくつかのテストを行いましたが、これは主題にいくらかの光を当てるかもしれないと思います...
app.js
:
var ...
, routes = require('./routes')
...;
...
console.log('@routes', routes);
...
のバージョン/routes/index.js
:
exports = function fn(){}; // outputs "@routes {}"
exports.fn = function fn(){}; // outputs "@routes { fn: [Function: fn] }"
module.exports = function fn(){}; // outputs "@routes function fn(){}"
module.exports.fn = function fn(){}; // outputs "@routes { fn: [Function: fn] }"
新しいファイルも追加しました:
./routes/index.js
:
module.exports = require('./not-index.js');
module.exports = require('./user.js');
./routes/not-index.js
:
exports = function fn(){};
./routes/user.js
:
exports = function user(){};
出力「@routes {}」を取得します
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
./routes/not-index.js
:
exports = function fn(){};
./routes/user.js
:
exports = function user(){};
「@routes { fn: {}, user: {} }」という出力が得られます
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
./routes/not-index.js
:
exports.fn = function fn(){};
./routes/user.js
:
exports.user = function user(){};
「@routes { user: [Function: user] }」という出力が得られます。 に変更user.js
すると{ ThisLoadedLast: [Function: ThisLoadedLast] }
、「@routes { ThisLoadedLast: [Function: ThisLoadedLast] }」という出力が得られます。
しかし、私たちが変更する./routes/index.js
と...
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');
./routes/not-index.js
:
exports.fn = function fn(){};
./routes/user.js
:
exports.ThisLoadedLast = function ThisLoadedLast(){};
... "@routes { fn: { fn: [Function: fn] }, ThisLoadedLast: { ThisLoadedLast: [Function: ThisLoadedLast] } }" を取得します
したがってmodule.exports
、モジュール定義で常に使用することをお勧めします。
Nodeの内部で何が起こっているのか完全には理解していませんが、これが役立つと確信しているので、これについてもっと理解できるかどうかコメントしてください.
-- 幸せなコーディング
このリンクは、上記の質問に答えるのに役立つことがわかりました。
http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/
他の投稿に追加するにはノード内のモジュールシステムが行います
var exports = module.exports
コードを実行する前に。したがって、 exports = foo を実行する場合は、おそらく module.exports = exports = foo を実行する必要がありますが、 exports.foo = foo を使用しても問題ありません。
var a = {},md={};
//まず、エクスポートと module.exports は同じ空のオブジェクトを指します
exp = a;//exports =a;
md.exp = a;//module.exports = a;
exp.attr = "change";
console.log(md.exp);//{attr:"change"}
// exp のプロパティを他のオブジェクトに向けるのではなく、他のオブジェクトに向ける場合。md.exp は空の Object {} になります
var a ={},md={};
exp =a;
md.exp =a;
exp = function(){ console.log('Do nothing...'); };
console.log(md.exp); //{}
これが結果です
console.log("module:");
console.log(module);
console.log("exports:");
console.log(exports);
console.log("module.exports:");
console.log(module.exports);
また:
if(module.exports === exports){
console.log("YES");
}else{
console.log("NO");
}
//YES
注: CommonJS 仕様では、エクスポート変数を使用してパブリック メンバーを公開することのみが許可されています。したがって、CommonJS 仕様と実際に互換性があるのは、名前付きエクスポート パターンだけです。module.exports の使用は、より幅広いモジュール定義パターンをサポートするために Node.js によって提供される拡張機能です。
これは、 Eloquent JavaScriptrequire()
から抜粋した最も単純な形式でどのように動作するかを示しています
問題
モジュールが、関数など、エクスポート オブジェクト以外の値を直接エクスポートすることはできません。たとえば、モジュールは、それが定義するオブジェクト型のコンストラクターのみをエクスポートする必要がある場合があります。現在、require はexports
作成したオブジェクトをエクスポートされた値として常に使用するため、これを行うことはできません。
解決策
モジュールに別の変数 を提供します。module
これは、プロパティ を持つオブジェクトですexports
。このプロパティは、最初は require によって作成された空のオブジェクトを指していますが、別のものをエクスポートするために別の値で上書きできます。
function require(name) {
if (name in require.cache)
return require.cache[name];
var code = new Function("exports, module", readFile(name));
var exports = {}, module = {exports: exports};
code(exports, module);
require.cache[name] = module.exports;
return module.exports;
}
require.cache = Object.create(null);
「モジュールのエクスポートのルートを関数 (コンストラクターなど) にする場合、または一度に 1 つのプロパティを構築するのではなく、1 つの割り当てで完全なオブジェクトをエクスポートする場合は、代わりに module.exports に割り当てます。輸出します。」- http://nodejs.org/api/modules.html
ノード js では、module.js ファイルを使用して module.load システムを実行します。ノードがファイルを実行するたびに、次のように js ファイルの内容をラップします。
'(function (exports, require, module, __filename, __dirname) {',+
//your js file content
'\n});'
ur js ソース コード内にこのラップがあるため、エクスポート、require、モジュールなどにアクセスできます。このアプローチが使用されるのは、js ファイルに書き込まれた機能を別のファイルに取得する方法が他にないためです。
ノードは、c++ を使用してこのラップされた関数を実行します。その時点で、この関数に渡されたエクスポート オブジェクトが満たされます。
この関数パラメータのエクスポートとモジュール内で確認できます。実際に exports は、モジュール コンストラクター関数のパブリック メンバーです。
次のコードを見てください
このコードを b.js にコピーします
console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();
このコードを a.js にコピーします
exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}
ノードを使用して実行するようになりました
module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true
object.keys of foo: name is function (){console.log('function to module exports')} function to module exports
a.js のコメント行を削除し、その行の上の行をコメント化し、b.js の最後の行を削除して実行します。
JavaScriptの世界では、パラメーターとして渡されたオブジェクトを再割り当てすることはできませんが、その関数のオブジェクトがパラメーターとして別の関数に設定されている場合、関数のパブリックメンバーを変更できます
require keyword を使用するときに関数を取得したい場合にのみ、 module.exports を使用してください。上記の例では、var foo = require(a.js); とします。foo を関数として呼び出すことができることがわかります。
これは、ノードのドキュメントが説明する方法です。