Node.jsでのmodule.exportsとexports


725

Node.jsモジュールで次のコントラクトを見つけました。

module.exports = exports = nano = function database_module(cfg) {...}

ここでは何が違うのか、なぜ両方を使用するのかmodule.exportsと思いexportsます。




6
Zeke

8
それはすべてリファレンスについてです。エクスポートは、module.exportsを指すローカル変数オブジェクトのようなものと考えてください。exportsの値を上書きすると、module.exportsへの参照が失われ、module.exportsが公開インターフェースとして公開されます。
Gabriel Llamas、2015年

14
クイックサマリー:両方を割り当て、同じオブジェクトexportsmodule.exportsポイントします(いずれかを再割り当てしない限り)。そして最後module.exportsに返されます。したがってexports、関数に再度割り当てた場合、関数は返されないため、期待できません。ただし、このような関数を割り当てた場合exports.func = function...、結果として生成されるのは、関数を値として持つfuncプロパティになります。あなたは、オブジェクトにプロパティを追加しましたのでexports..を指した
ムハンマドUmer

回答:


426

設定module.exportsにより、database_module関数は関数のように呼び出されrequiredます。exportsnodeはオブジェクトmodule.exports参照をエクスポートするため、設定するだけでは関数をエクスポートできません。次のコードは、ユーザーが関数を呼び出すことを許可しません。

module.js

以下は動作しません。

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.jsexports現在参照しているオブジェクトをエクスポートしませんが、exports元々参照しているオブジェクトのプロパティをエクスポートします。が、Node.jsのがないオブジェクトのエクスポートmodule.exportsは、関数のようにそれを呼び出すことができるように、参照を。


2番目に重要でない理由

両方module.exportsを設定し、以前にエクスポートされたオブジェクトを参照しないexportsようにしexportsます。両方を設定することexportsで、速記として使用し、将来の潜在的なバグを回避します。

exports.prop = true 代わりにmodule.exports.prop = trueを使用すると、文字が節約され、混乱を回避できます。


8
@ajostergaard:たまたま、OPの例の元となったライブラリの名前になります。モジュールでは、作成者がのnano.version = '3.3'代わりにを書くことができますmodule.exports.version = '3.3'。(これnanoはローカル変数であり、モジュールのエクスポートが設定される少し前宣言されていることに注意してください。)
josh3736

3
@lime-感謝-それが大部分は無関係であるとは嬉しいです。そうでなければ、すべてを完全に誤解したことになります。:-| :)
ostergaard 2013年

こんにちはライム、これはかなり古い答えですが、何かを明確にしていただければ幸いです。設定しmodule.exports exports、設定しなかった場合でも、コードは機能しますか?助けてくれてありがとう!
Asad Saeeduddin 2013

1
@Asadはい、設定すると適切にエクスポートされますmodule.exports
Lime

@Liam貴重な回答をありがとう。いくつかのクエリ-server.jsのエントリで、module.exportsとexportsの値は何になると予想されますか?module.exportsはnullである必要があり、エクスポートは空のオブジェクトに設定されていますか?これはレガシーですか、それともエクスポートとmodule.exportsを2つの異なるオブジェクトにポイントする有効な使用例がありますか?
Sushil 2013年

504

質問はかなり前に回答され、受け入れられましたが、2セントを共有したいと思います。

ファイルの冒頭に(説明のために)次のようなものがあると想像できます。

var module = new Module(...);
var exports = module.exports;

ここに画像の説明を入力してください

したがって、あなたが何をしてもmodule.exportsexports他の場所からそのモジュールを必要とするときに、モジュールから返されないことに注意してください。

したがって、次のようなことをすると:

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

2つの関数aを追加bし、その上にmodule.exportsポイントがあるオブジェクトにも追加するためtypeof、返される結果はobject{ a: [Function], b: [Function] }

もちろん、これは、module.exportsこの例での代わりにを使用している場合と同じ結果になりますexports

これは、module.exportsエクスポートされた値のコンテナのように動作させたい場合です。一方、コンストラクター関数のみをエクスポートする場合は、module.exportsまたはexports;の使用について知っておくべきことがいくつかあります(module.exportsこれは、何かではなく、必要なときに返されますexport)。

module.exports = function Something() {
    console.log('bla bla');
}

これでtypeof結果が'function'返されます。これを要求して、次のようにすぐに呼び出す
var x = require('./file1.js')();ことができます。返される結果を関数に上書きするためです。

ただし、exports次のようなものは使用できません。

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

有するためexports、参照が指していないオブジェクトにもはやmodule.exports点は、それほど関係がないexportsmodule.exportsもう。この場合module.exportsでも、{}返される空のオブジェクトを指します。

別のトピックから受け入れられた回答も役立つはずです: JavaScriptは参照渡しですか?


2
ニースの説明が、私はまだあなたが完全に省略することができますどのように理解していないmodule.exportsモジュールから、例えばこの中にnpmパッケージ:github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein

4
@Imray説明はこちら:JavaScriptは参照渡しですか? exports.a = function(){}; works, exports = function(){} doesn't work
cirpo

29
oooo最後に、この回答で説明しています。基本的にエクスポートとは、プロパティを追加できるオブジェクトを指しますが、関数に再度割り当てると、元のオブジェクトにプロパティをアタッチする必要がなくなります。module.exportsがまだそのオブジェクトを指しており、それが返されているため、export reference functionを実行します。エクスポートは基本的にガベージコレクションされていると言えます。
Muhammad Umer 2015年

5
それでは、使用のポイントは何exportsですか?module.exportsそれが単なる変数の再割り当てである場合は、なぜ常に使用しないのですか?私を混乱させているようです。
jedd.ahyoung 2015

1
@ jedd.ahyoung exports.something代わりに書くほうが面倒ではありませんmodule.exports.something
Srle

209

基本的に答えは、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の一部として何もエクスポートまたは返されません。


8
Lost me hereexports = module.exports = {};
Giant Elk、

2
私はこれが最良の答えであるべきだと思います、それは@William func()の答えで失敗する理由を説明しています!
2015

2
exports = module.exports = app;コードの最後の行に追加する利点はないよう です。ように思えるmodule.exports輸出されますと、我々が使用することは決してありませんexportsもう一度、コードの最後の行にありますので、。では、単に追加しないのはなぜmodule.exports = app;
ですか

79

最初はmodule.exports=exportsrequire関数はオブジェクトがmodule.exports参照するオブジェクトを返します。

我々があればプロパティを追加したオブジェクトに、たとえばexports.a=1、その後、module.exportsは、輸出はまだ同じオブジェクトを参照してください。したがって、requireを呼び出してモジュールを変数に割り当てると、変数のプロパティはaになり、その値は1になります。

しかし、それらの1つ(たとえば)をオーバーライドする場合exports=function(){}、それらは今は異なります。exportsは新しいオブジェクトを参照し、module.exportsは元のオブジェクトを参照します。また、ファイルが必要な場合、module.exportsは新しいオブジェクトを参照しないため、新しいオブジェクトは返されません。

私にとって、私は新しいプロパティを追加し続けるか、それらの両方を新しいオブジェクトにオーバーライドします。オーバーライドするだけでは正しくありません。それmodule.exportsが本当のボスだということを覚えておいてください。


1
ええ、これが実際の答えです。簡潔で明確です。他の人は正しいかもしれませんが派手な言葉でいっぱいで、この質問の答えに正確に焦点を当てていないかもしれません。
Khoa

これははるかに明確な答えです!:あなたはそれをブックマークしたい場合には、これは正確なリンクですstackoverflow.com/questions/7137397/...
lambdarookie

56

exportsそしてmodule.exportsあなたは再割り当てしない限り、同じexportsあなたのモジュール内で。

それについて考える最も簡単な方法は、この行が暗黙的にすべてのモジュールの先頭にあると考えることです。

var exports = module.exports = {};

モジュール内でを再割り当てするとexports、モジュール内で再度割り当てられ、と等しくなくなりmodule.exportsます。これが、関数をエクスポートする場合に必要な理由です。

module.exports = function() { ... }

あなたは、単にあなたに割り当てられている場合function() { ... }にはexports、あなたが再割り当てされますexportsと、もはやポイントにmodule.exports

module.exports毎回関数を参照したくない場合は、次のようにすることができます。

module.exports = exports = function() { ... }

それmodule.exportsが左端の引数であることに注意してください。

プロパティのexports再割り当ては行わないため、プロパティのアタッチは同じではありません。これが機能する理由です

exports.foo = function() { ... }

9
これは、すべての回答の中から最も理解しやすいものでした。
Adarsh Konchady 16


1
この機能を理解するためのシンプルで簡単な方法。
FilipeCanatto

27

JavaScriptは参照のコピーによってオブジェクトを渡します

JavaScriptでオブジェクトが参照によって渡される方法とは微妙に異なります。

exportsそして、module.exports同じオブジェクトをポイントし、両方。exports変数でありmodule.exports、モジュールオブジェクトの属性です。

私がこのようなものを書くとしましょう:

exports = {a:1};
module.exports = {b:12};

exportsそしてmodule.exports今、別のオブジェクトを指します。エクスポートを変更してもmodule.exportsは変更されなくなりました。

インポート機能が検査module.exportsすると{b:12}


6
ベストアンサーimho!
AJさん2016年

1
「JavaScriptは参照渡し」– いいえ
xehpuk 2018年

13

私はいくつかのテストを行うだけです、それは、nodejsのモジュールコード内で、次のようになるはずです:

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

そう:

1:

exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.

2:

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

3:しかし、この場合

module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)

ライマンは、module.exportsノードが「実際の取引」になるようなものですが、(上記のケース2)を使用している場合exportsmodule.exports除いて、ある時点ですべてを追加する必要があります。exports.namespaceノードが走ったextends(module.exports, exports);の追加すべての「名前空間」exportsへのmodule.exportsオブジェクトを?つまり、使用しているexports場合は、おそらくプロパティを設定する必要があるのでしょうか。
Cody

11

以下は、Manning出版物のアクションブックのnode.jsのノードモジュールについて書かれた適切な説明です。 アプリケーションで最終的にエクスポートされるのはmodule.exportsです。exportsは単にmodule.exportsへのグローバル参照として設定されます。これは、最初はプロパティを追加できる空のオブジェクトとして定義されています。したがって、exports.myFuncmodule.exports.myFuncの省略形にすぎません。 その結果、exportsが他の値に設定されている場合、module.exportsexportsの間の参照壊れます。そのためmodule.exportsは



実際にエクスポートされるものは、エクスポートは期待どおりに機能しなくなります。モジュール.exportsを参照しなくなります。そのリンクを維持したい場合は、次のようにmodule.exports 参照エクスポートを再度作成できます。

module.exports = exports = db;

8

私はいくつかのテストを行いました、そしてこれは主題にいくつかの光を当てるかもしれません...

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:[関数:fn]}、ThisLoadedLast:{ThisLoadedLast:[関数:ThisLoadedLast]}}」が得られます

だから私は常に使用することをお勧めします module.exportsあなたのモジュール定義でをおします。

Nodeで内部的に何が起こっているのか完全には理解していませんが、これが役立つと確信しているので、これをもっと理解できるかどうかコメントしてください。

-ハッピーコーディング


それらは不必要に複雑で混乱していると思います。透明で直感的である必要があります。
ngungo 14

同意する。ネームスペースの状況によっては役立つ場合がありますが、通常は何も作成または中断しません。
コーディ14

4

これはrequire()Eloquent JavaScriptから抜粋した最も単純な形式でどのように機能するかを示しています

問題 モジュールが関数など、exportsオブジェクト以外の値を直接エクスポートすることはできません。たとえば、モジュールは、モジュールが定義するオブジェクトタイプのコンストラクタのみをエクスポートする場合があります。現時点では、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);

私はこれをNodeで再作成し、いくつかのことをテストする必要がありました。基本的に、モジュール用に作成された内部関数は、exportsオブジェクトを返すことすらありません。したがって、「exports」オブジェクトは実際にはモジュールで再割り当てされません。たとえば、exports =「this is now a string」を直接書き込もうとした場合などです。オブジェクトは参照としてのみ存在します。これは私が今まで適切に理解できなかったと私が思う行動です。
danielgormly 2016

4

これはの結果です

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仕様では、パブリック変数を公開するためのexports変数の使用のみが許可されています。したがって、名前付きエクスポートパターンは、CommonJS仕様と実際に互換性のある唯一のパターンです。module.exportsの使用は、より広範なモジュール定義パターンをサポートするためにNode.jsによって提供される拡張機能です。


4
var a = {},md={};

//まず、exportsとmodule.exportsが同じ空のオブジェクトを指す

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

// expを他のオブジェクトにポイントするのではなく、他のオブジェクトにポイントする場合。md.expは空のオブジェクト{}になります

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}

4

ドキュメントから

exports変数は、モジュールのファイルレベルのスコープ内で使用でき、モジュールが評価される前にmodule.exportsの値が割り当てられます。

これによりショートカットが許可されるため、module.exports.f = ...をexports.f = ...としてより簡潔に記述できます。ただし、他の変数と同様に、新しい値がエクスポートに割り当てられている場合は、 module.exportsにバインドされなくなりました:

これは、module.exportsを指す変数です。


4

このリンクは、上記の質問に答えるのに役立ちました。

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を使用するのが適切です。


gitリンクが壊れている
Jesse Hattabaugh 2017

リンクが修正されました。
パヴェルGościcki

3

「モジュールのエクスポートのルートを関数(コンストラクターなど)にする場合、または一度に1つのプロパティを作成するのではなく、1つの割り当てでオブジェクト全体をエクスポートする場合は、代わりにmodule.exportsに割り当てます。輸出。」- http://nodejs.org/api/modules.html


3

module.exports そして exportsモジュールの前に同じオブジェクトの両方の点が評価されます。

module.exports オブジェクトに追加したすべてのプロパティは、モジュールが別のモジュールのusing requireステートメントで使用されている場合に使用できます。exports同じもので利用できるショートカットです。例えば:

module.exports.add = (a, b) => a+b

書くことと同じです:

exports.add = (a, b) => a+b

したがって、exports変数に新しい値を割り当てない限り問題ありません。このようなことをすると:

exports = (a, b) => a+b 

新しい値を割り当てるexportsと、エクスポートされたオブジェクトへの参照がなくなり、モジュールに対してローカルのままになります。

module.exports利用可能にされた初期オブジェクトに新しいプロパティを追加するのではなく、に新しい値を割り当てることを計画している場合は、おそらく以下のようにすることを検討する必要があります。

module.exports = exports = (a, b) => a+b

Node.jsのWebサイトは、これについて非常によく説明しています。


2

1.exports->シングルトンユーティリティとして使用
2. module- exports-> サービス、モデルなどの論理オブジェクトとして使用


2

2つの方法で1つのモジュールを作成しましょう:

一方通行

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

二番目の方法

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

そして、これがrequire()がモジュールを統合する方法です

最初の方法:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

二番目の方法

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}

2

ここで両方が使用される理由

私は、彼らはちょうどそれは明らかにしたいと考えているmodule.exportsexportsnano同じ機能をポイント-あなたは、ファイル内の関数を呼び出すためにどちらかの変数を使用することができます。nano関数が実行する内容にいくつかのコンテキストを提供します。

exportsエクスポートされないので(エクスポートされるだけmodule.exportsです)、なぜそれも上書きするのですか?

冗長性のトレードオフexportsによりmodule.exports、ファイル内ではなく使用するなど、将来のバグのリスクが制限されます。また、提供して明確化していることmodule.exportsexports、実際にある同じ値を指します。


module.exportsexports

再割り当てを行わない限り(module.exportsまたはexports、両方が参照するオブジェクトに値を追加しない限り)、問題は発生せず、exportsより簡潔にするために安全に使用できます。

いずれかを非オブジェクトに割り当てると、意図module.exports的に特定のもの(関数など)になりたくない場合、混乱する可能性がある異なる場所を指すようになります。

設定exportsあなたが設定する必要がありますように、非対象にしてもあまり意味がありません。module.exports = exports他のファイルでそれを使用できるように終わり。

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

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

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

module.exports = 'hello';
console.log(module.exports === exports); // false

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

なぜmodule.exports関数に割り当てるのですか?

もっと簡潔に!2番目の例がどれだけ短いかを比較します。

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world


2

ここに画像の説明を入力してください

作成する各ファイルはモジュールです。モジュールはオブジェクトです。exports : {}デフォルトでは空のオブジェクトと呼ばれるプロパティがあります。

次のようなオブジェクトの機能/ミドルウェアを作成し、この空の輸出に追加することができexports.findById() => { ... } 、その後requireどこでもあなたのアプリと使用中の...

controllers / user.js

exports.findById = () => {
    //  do something
}

使用するにはroutes.jsで必要です:

const {findyId} = './controllers/user'

2

違いを理解するには、まず実行時にNode.jsがすべてのモジュールに対して何を行うかを理解する必要があります。Node.jsは、すべてのモジュールのラッパー関数を作成します。

 (function(exports, require, module, __filename, __dirname) {

 })()

最初のパラメータexportsは空のオブジェクトであり、3番目のパラメータmoduleは多くのプロパティを持つオブジェクトであり、プロパティの1つはという名前であることに注意してくださいexports。これは何exportsから来るのか、何module.exportsから来るのかです。前者は可変オブジェクトであり、後者はmoduleオブジェクトのプロパティです。

モジュール内で、Node.jsは最初にこの処理を自動的に実行しmodule.exports = exports最終的にを返しますmodule.exports

したがってexports、値をに再割り当てしても、には何の影響もないことがわかりますmodule.exports。(単にexports別の新しいオブジェクトをポイントしているが、module.exportsまだ古いオブジェクトを保持しているためexports

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

しかし、のプロパティを更新した場合exports、それは確かにに影響を与えmodule.exportsます。どちらも同じオブジェクトを指しているためです。

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

またmodule.exports、別の値をに再割り当てすると、exports更新しても意味がないように見えることに注意してください。別のオブジェクトを指しているexportsため、すべての更新は無視されmodule.exportsます。

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}

0

ノードjsのmodule.jsファイルは、ノードがファイルを実行するたびにmodule.load system.everytimeを実行するために使用され、次のようにjsファイルのコンテンツをラップします

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

このur jsソースコード内でのラッピングにより、エクスポート、要求、モジュールなどにアクセスできます。jsファイルに機能を書き込む他の方法がないため、このアプローチが使用されます。

次に、ノードはC ++を使用してこのラップされた関数を実行します。その時点で、この関数に渡されたエクスポートオブジェクトが入力されます。

この関数のパラメーターのエクスポートとモジュールを見ることができます。実際にエクスポートは、モジュールコンストラクター関数のパブリックメンバーです。

次のコードを見てください

このコードを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

exportsは[object Object]です

fooのobject.keys:名前は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を関数として呼び出すことができます。

これは、ノードのドキュメントがそれを説明する方法です。「エクスポートオブジェクトはモジュールシステムによって作成されます。これは受け入れられない場合があり、多くの場合、モジュールを特定のクラスのインスタンスにする必要があります。これを行うには、目的のエクスポートオブジェクトをmodule.exportsに割り当てます。」


0
  1. 両方とも同じmodule.exportsexports指しfunction database_module(cfg) {...}ます。

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"

    b3行目でをに変更するaと、出力が逆になります。結論は:

    ab独立しています。

  2. したがって、以下module.exports = exports = nano = function database_module(cfg) {...}と同等です。

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;

    上記がmodule.jsであると仮定しfoo.jsます。の利点module.exports = exports = nano = function database_module(cfg) {...}は明らかです。

    • ではfoo.js、以来module.exportsですrequire('./module.js')

      var output = require('./modules.js')();
    • In moduls.js:のexports代わりに使用できますmodule.exports

したがって、両方が同じものexportsmodule.exports指している場合は、あなたは幸せになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.