web-dev-qa-db-ja.com

Node.js module.exportsの目的は何ですか?またそれをどのように使用しますか?

Node.js module.exportsの目的は何ですか?またそれをどのように使用しますか?

私はこれに関する情報を見つけることができないようですが、私はソースコードでそれをよく見るのでNode.jsのかなり重要な部分のようです。

Node.jsのドキュメントによると

モジュール

現在のmoduleへの参照。特にmodule.exportsはexportsオブジェクトと同じです。詳しくはsrc/node.jsをご覧ください。

しかし、これは本当に役に立ちません。

module.exportsは正確には何をしていますか?そして簡単な例はどうなるでしょうか?

1343
mrwooster

module.exports は、require呼び出しの結果として実際に返されるオブジェクトです。

exports変数は、最初は同じオブジェクトに設定されています(つまり、省略形の「エイリアス」です)。そのため、モジュールコードでは、通常次のように記述します。

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

内部スコープの関数myFunc1およびmyFunc2をエクスポート(または「公開」)するため。

そして呼び出しコードであなたが使用するでしょう:

var m = require('./mymodule');
m.myFunc1();

最後の行は、requireの結果が(通常)単なるプロパティにアクセスできる単なるオブジェクトであることを示しています。

注意:exportsを上書きした場合、それはもはやmodule.exportsを参照しません。したがって、新しいオブジェクト(または関数参照)をexportsに割り当てたい場合は、その新しいオブジェクトもmodule.exportsに割り当てる必要があります。


exportsオブジェクトに追加された名前は、追加する値に対してモジュールの内部スコープの名前と同じである必要はないことに注意する価値があります。

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

に続く:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
1518
Alnitak

これはすでに回答されていますが、説明を加えたいと思います。

exportsmodule.exportsの両方を使用して、次のようにコードをアプリケーションにインポートできます。

var mycode = require('./path/to/mycode');

基本的な使用例(ExpressJSのサンプルコードなど)は、.jsファイル内のexportsオブジェクトにプロパティを設定し、それをrequire()を使ってインポートすることです

単純な例では、次のようになります。

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

...あなたのアプリケーション(web.js、あるいは他のあらゆる.jsファイル)で:

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

簡単に言うと、必要なファイルは単一のオブジェクトを返す関数と考えることができ、exportsに設定することで返されるオブジェクトにプロパティ(文字列、数値、配列、関数など)を追加できます。

ときには、単にプロパティを持つオブジェクトではなく、require()呼び出しから返されたオブジェクトを、呼び出すことができる関数にしたいことがあります。その場合は、次のようにmodule.exportsも設定する必要があります。

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

Exportsとmodule.exportsの違いは/で説明されています - この答えはここ です。

206
Jed Watson

NodeJSモジュールメカニズムは、 CommonJS に基づいていることに注意してください。これは、RequireJSだけでなく、SproutCoreCouchDBWakandaOrientDBArangoDBRingoJSTeaJSSilkJScurl.js、または偶数Adobe Photoshop(経由で PSLib )。既知の実装の完全なリストを見つけることができます こちら

モジュールがノード固有の機能またはモジュールを使用しない限り、CommonJS標準の一部ではないmodule.exportsの代わりにexportsを使用することを強くお勧めします、その後、他の実装ではほとんどサポートされません。

別のNodeJS固有の機能は、このスレッドでJed Watsonが提供した最後の例のようにプロパティとメソッドを単に追加する代わりに、exportsに新しいオブジェクトへの参照を割り当てることです。このがCommonJSモジュールメカニズムの循環参照サポートを破るため、私は個人的にこの慣行を推奨しません。その場合、すべての実装でサポートされるわけではなく、Jedの例はこの方法(または同様の方法)で記述して、より汎用的なモジュールを提供する必要があります。

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

またはES6機能を使用する

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS:AppceleratorもCommonJSモジュールを実装しているように見えますが、循環参照はサポートされていません(参照: AppceleratorおよびCommonJSモジュール(キャッシュおよび循環参照)

60

新しいオブジェクトへの参照をexportsmodules.exports、あるいはその両方に代入する場合に注意しなければならないことがいくつかあります。

1.以前のオリジナルのexportsまたはmodule.exportsに関連付けられていたすべてのプロパティ/メソッドは、もちろんエクスポートされたオブジェクトが別の新しいものを参照するため、失われます。

これは明らかですが、 既存のモジュールの先頭にエクスポートされたメソッドを追加する場合、ネイティブのエクスポートされたオブジェクトが最後に別のオブジェクトを参照していないことを確認してください

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. exportsまたはmodule.exportsのいずれかが新しい値を参照する場合、それらは同じオブジェクトを参照しません。

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

トリッキーな結果。参照をexportsmodule.exportsの両方に変更した場合、どのAPIが公開されているかがわかりにくい(module.exportsが勝ったように見えます)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 
32

module.exportsプロパティまたはexportsオブジェクトにより、モジュールはアプリケーションと共有するものを選択できます。

enter image description here

私は利用可能なmodule_exportに関するビデオを持っています ここ

28
anish

プログラムコードを複数のファイルに分割する場合、module.exportsは変数と関数をモジュールの利用者に公開するために使用されます。ソースファイルのrequire()呼び出しは、モジュールからロードされた対応するmodule.exportsに置き換えられます。

モジュールを書くときに覚えておく

  • モジュールのロードはキャッシュされ、最初の呼び出しだけがJavaScriptを評価します。
  • すべてをエクスポートする必要はなく、モジュール内でローカル変数と関数を使用することは可能です。
  • module.exportsオブジェクトはexports速記としても利用可能です。しかし、単独の関数を返すときは、常にmodule.exportsを使用してください。

module exports diagram

によると: "モジュールパート2 - モジュールを書く"

17
pspi

参照リンクは次のようになります。

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

関数や変数などのexportsまたはmodule.exportsのプロパティは、外部に公開されます。 

もっと注意を払う必要があるものがあります:override輸出しないでください。

どうして ?

module.exportsの参照だけをエクスポートするので、エクスポートにプロパティを追加できますが、エクスポートを上書きすると、参照リンクが壊れます。

良い例え :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

悪い例:

exports = 'william';

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

次のように、関数や変数を1つだけ公開したい場合は、

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

このモジュールは1つの関数のみを公開しており、nameのプロパティは外部に対してプライベートです。

8
qianjiahao

Node.jsをダウンロードしてインストールすると、 http、sys などのデフォルトまたは既存のモジュールがnode.jsにあります。 

それらは既にnode.jsに入っているので、これらのモジュールを使いたいときは基本的に import modules のようにしますが、なぜでしょうかなぜならそれらは既にnode.jsに存在しているからです。インポートは、それらをnode.jsから取り出してそれらをプログラムに入れることに似ています。そしてそれらを使用します。

Exports は正反対ですが、あなたが欲しいモジュールを作成しているのであれば、モジュールAddition.jsをnode.jsに入れて、それをエクスポートすることによって行います。

ここで何かを書く前に、 module.exports.additionTwo exports.additionTwoと同じです

ええと、それが理由です、私たちは好きです

exports.additionTwo = function(x)
{return x+2;};

道に気をつけて

Addition.jsモジュールを作成したとしましょう。 

exports.additionTwo = function(x){
return x + 2;
};

NODE.JSコマンドでこれを実行すると、プロンプトが表示されます。

node
var run = require('addition.js');

これは言ってエラーになります 

エラー:module Addition.jsが見つかりません

これは、パスについて言及していないため、node.jsプロセスはAddition.jsを実行できないためです。そのため、NODE_PATHを使用してパスを設定できます。

set NODE_PATH = path/to/your/additon.js

これで、これはエラーなく正常に実行されるはずです。

もう1つ、NODE_PATHを設定しないでAddition.jsファイルを実行し、nodejsコマンドのプロンプトに戻ることもできます。

node
var run = require('./addition.js');

ここでは現在のディレクトリ./にあると言ってパスを提供しているので、これも正常に実行されるはずです。 

5
JumpMan

モジュールは、関連するコードを単一のコード単位にカプセル化します。モジュールを作成するとき、これは関連するすべての機能をファイルに移動することとして解釈できます。 

2つの関数を含むファイルHello.jsがあるとします。

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

コードの有用性が複数の呼び出しである場合にのみ関数を作成します。

World.jsと言う別のファイルに関数の有用性を高めたいとします。この場合、ファイルのエクスポートはmodule.exportsによって取得できる画像になります。

下記のコードで両方の関数をエクスポートすることができます。

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

これらの関数を使うためには、今度はWorld.jsにファイル名を要求するだけです。

var world= require("./hello.js");
2
Shantanu Madane

目的は次のとおりです。

モジュラープログラミングは、プログラムの機能を独立した交換可能なモジュールに分離することを強調するソフトウェア設計手法であり、それぞれが目的の1つの側面のみを実行するために必要なすべてのものを含む機能性.

ウィキペディア

私はそれがモジュラー/再利用可能なコードなしで大きなプログラムを書くことが難しくなると思います。 nodejsでは、公開するものを定義するmodule.exportsを利用してモジュラープログラムを作成し、requireを使用してプログラムを構成できます。

この例を試してください:

fileLog.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

stdoutLog.js

function log(string) { console.log(string); }

module.exports = log;

program.js

const log = require('./stdoutLog.js')

log('hello world!');

実行

$ node program.js

こんにちは世界!

./fileLog.js に対して ./stdoutLog.js を入れ替えてみてください。

1
Moriarty

モジュールシステムの目的は何ですか?

それは以下のことを達成します。

  1. ファイルが肥大化するのを防ぎます 非常に大きなサイズにします。とファイルを持つその中の5000行のコードは、通常、開発中に対処するのが本当に難しいです。
  2. 懸案事項の分離を強制します。 コードを複数のファイルに分割することで、すべてのファイルに適切なファイル名を付けることができます。このようにして、すべてのモジュールが何をするのか、そしてどこでそれを見つけるべきかを容易に識別することができます(まだあなたの責任である論理的なディレクトリ構造を作ったと仮定して)。

モジュールを持つことで、コードの特定部分を見つけやすくなり、コードの保守性が向上します。

それはどのように機能しますか?

NodejSは次のように動作するCommomJSモジュールシステムを使用します。

  1. ファイルが何かをエクスポートしたい場合はmodule.export構文を使ってそれを宣言しなければなりません
  2. ファイルが何かをインポートしたい場合、require('file')構文を使ってそれを宣言しなければなりません。

例:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

知っておくべきその他の便利なこと:

  1. モジュールはキャッシュされています 。あなたが2つの異なるファイルに同じモジュールをロードしているとき、モジュールは一度だけロードされる必要があります。同じモジュールに対してrequire()が2度目に呼び出されると、キャッシュから引き出されます。
  2. モジュールは同期的にロードされます 。非同期の場合、この動作は必須です。require()から取得したオブジェクトにすぐにアクセスできませんでした。
0