820

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

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

module.exportsここでととの違いは何なのだろうかexports

4

24 に答える 24

454

設定module.exportsすると、database_module関数を関数のように呼び出すことができますrequired。ノードがオブジェクト参照exportsをエクスポートするため、設定するだけでは関数をエクスポートできません。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.jsは現在参照しているオブジェクトをエクスポートしませんexportsが、最初に参照しているオブジェクトのプロパティをエクスポートしますexportsNode.jsはオブジェクト参照をエクスポートしますがmodule.exports、関数のように呼び出すことができます。


2番目に重要でない理由

それらは両方module.exportsを設定し、以前にエクスポートされたオブジェクトを参照していないexportsことを確認します。exports両方を設定することexportsで、省略形として使用し、後で潜在的なバグを回避できます。

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

于 2011-08-22T03:38:53.303 に答える
217

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

于 2013-07-30T10:24:07.960 に答える
101

最初は、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そして、それが本当の上司であることを覚えておいてください。

于 2013-08-12T02:16:32.320 に答える
34

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

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

exportsどちらも同じオブジェクトをmodule.exports指しています。exports変数でmodule.exportsあり、モジュール オブジェクトの属性です。

次のように書いたとします。

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

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

インポート機能が検査module.exportsすると、それが取得されます{b:12}

于 2015-02-18T17:14:54.737 に答える
12

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



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

module.exports = exports = db;
于 2015-07-14T12:47:39.213 に答える
9

私はいくつかのテストを行いましたが、これは主題にいくらかの光を当てるかもしれないと思います...

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の内部で何が起こっているのか完全には理解していませんが、これが役立つと確信しているので、これについてもっと理解できるかどうかコメントしてください.

-- 幸せなコーディング

于 2014-03-24T23:00:37.907 に答える
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 を使用しても問題ありません。

于 2013-07-02T13:46:51.280 に答える
4
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); //{}
于 2016-10-18T01:27:51.217 に答える
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 仕様では、エクスポート変数を使用してパブリック メンバーを公開することのみが許可されています。したがって、CommonJS 仕様と実際に互換性があるのは、名前付きエクスポート パターンだけです。module.exports の使用は、より幅広いモジュール定義パターンをサポートするために Node.js によって提供される拡張機能です。

于 2015-10-27T13:30:31.983 に答える
4

これは、 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);
于 2015-09-10T04:02:28.947 に答える
3

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

于 2014-03-05T00:38:17.913 に答える
0

ノード 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

exports は [object Object]

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 を関数として呼び出すことができることがわかります。

これは、ノードのドキュメントが説明する方法です。

于 2014-01-09T12:55:57.667 に答える