Node.js-module.exportsをコンストラクターとして使用


120

Node.jsマニュアルによると:

モジュールのエクスポートのルートを関数(コンストラクターなど)にする場合、または一度に1つのプロパティを作成するのではなく、1つの割り当てでオブジェクト全体をエクスポートする場合は、エクスポートではなくmodule.exportsに割り当てます。 。

与えられた例は:

// file: square.js
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

次のように使用します:

var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

私の質問:例ではオブジェクトとして正方形を使用しないのはなぜですか?以下は有効であり、例をより「オブジェクト指向」にしますか?

var Square = require('./square.js');
var mySquare = new Square(2);
console.log('The area of my square is ' + mySquare.area());

1
あなたの例は構文エラーです。に名前squareを変更しSquareた後はnew square()存在しません。
スキマ

3
すみません、それはタイプミスでした。修正しました。私の意図は、大文字で始まるオブジェクト/関数名と小文字で始まるインスタンス名を表示することでした。
Naresh

4
私も同じくらい考えました、それで私は自分のやり方で答えを書きました。他の人が同じようにモジュールを見て本当に良かったと言いたかっただけです。私はしばしば新しいキーワードを使用し、モジュールを編成して単一のコンストラクター関数をエクスポートします。ソリューションの読みやすさと概念化が容易になると思います。どのような構成を使用するかが一目でわかります。私のように考えることに対する称賛;)
スキマ

回答:


173

CommonJSモジュールでは、2つの方法でエクスポートされたプロパティを定義できます。どちらの場合でも、オブジェクト/関数を返します。関数はJavaScriptの第一級市民であるため、オブジェクトと同じように機能できます(技術的にはオブジェクトです)。そうは言っても、newキーワードの使用に関する質問には簡単な答えがあります:はい。説明します...

モジュールのエクスポート

exports提供された変数を使用して、プロパティを添付できます。別のモジュールで必要になると、それらの割り当てプロパティが使用可能になります。または、module.exportsプロパティにオブジェクトを割り当てることもできます。どちらの場合でもrequire()、によって返されるのはの値への参照ですmodule.exports

モジュールの定義方法の疑似コード例:

var theModule = {
  exports: {}
};

(function(module, exports, require) {

  // Your module code goes here

})(theModule, theModule.exports, theRequireFunction);

上記の例module.exportsexportsは、同じオブジェクトです。クールな部分は、CommonJSモジュールには何も表示されないことです。これは、システム全体がそれを処理するため、exportsプロパティと、 module.exportsが行うのと同じこと。

コンストラクターで必要

関数を直接アタッチできるので、module.exports基本的には関数を返すことができ、他の関数と同様に、コンストラクターとして管理できます(JavaScriptの関数とコンストラクターの唯一の違いは、それをどのように使用するかということです。違いはありません。)

したがって、以下は完全に優れたコードであり、個人的にはそれを推奨しています。

// My module
function MyObject(bar) {
  this.bar = bar;
}

MyObject.prototype.foo = function foo() {
  console.log(this.bar);
};

module.exports = MyObject;

// In another module:
var MyObjectOrSomeCleverName = require("./my_object.js");
var my_obj_instance = new MyObjectOrSomeCleverName("foobar");
my_obj_instance.foo(); // => "foobar"

非コンストラクターに必要

同じことは、非コンストラクターのような関数にも当てはまります。

// My Module
exports.someFunction = function someFunction(msg) {
  console.log(msg);
}

// In another module
var MyModule = require("./my_module.js");
MyModule.someFunction("foobar"); // => "foobar"

2
簡単にrequire( './ my-object.js')( "foobar")を実行できますか?または、別のユースケースのrequire( 'module')(params)構文ですか?
Hampus Ahlgren 2014

1
あなたを止めるものは何もありません、それはすべて単なるJavaScriptです。したがって、はい、より短い構文を使用できます。
スキマ

3
モジュールの定義方法の疑似コード例は、Node.jsモジュールシステムの理解を完全に明確にしました。ありがとうございました!
Nitax 2016

130

私の意見では、node.jsの例のいくつかはかなり不自然です。

あなたは現実の世界でこのようなものを見ることを期待するかもしれません

// square.js
function Square(width) {

  if (!(this instanceof Square)) {
    return new Square(width);
  }

  this.width = width;
};

Square.prototype.area = function area() {
  return Math.pow(this.width, 2);
};

module.exports = Square;

使用法

var Square = require("./square");

// you can use `new` keyword
var s = new Square(5);
s.area(); // 25

// or you can skip it!
var s2 = Square(10);
s2.area(); // 100

ES6の人向け

class Square {
  constructor(width) {
    this.width = width;
  }
  area() {
    return Math.pow(this.width, 2);
  }
}

export default Square;

ES6での使用

import Square from "./square";
// ...

クラスを使用する場合、キーワードを使用してそれをインスタンス化する必要ありますnew。他はすべて同じままです。


3
異常に簡潔な構造!
Christophe Marois、2014

1
したがって、<ES6の例では、使用する場合newと使用しない場合の違いはないようです。しかし、それはあなたがそのチェックを受けているからというだけthis instanceof squareですか?もしそうなら、そのメカニズムは正確に何をしているのですか?
arichards 2016

1
質問は、私が持っていたし、それが他の人に便利だ場合には、見上げ:どこにあるimportexport定義されましたか?これらはECMAScript 6(ES6)の予約済みキーワードです。ES6より前は、ライブラリを使用してモジュールを管理する必要がありました。ノードのモジュール化は、CommonJSライブラリのモジュールをモデルにしています。何であるdefaultではexport default Squareこれは、「ファイル」をインポートするだけで、そのファイルから他の特定のエクスポートをインポートしない場合に何をインポートするかを指定します。それらが存在する限り、私はこれらのページが役に立ったと感じました:spring.io/understanding/javascript-modulesおよびexploringjs.com/es6/ch_modules.html
arichards

1

この質問は実際にはどのようにrequire()機能するかとは関係ありません。基本的に、module.exportsモジュールで設定したものはすべて、そのrequire()呼び出しから返されます。

これは次と同等です。

var square = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

new呼び出すときにキーワードは必要ありませんsquare。から関数インスタンス自体を返すのではなくsquare、最後に新しいオブジェクトを返します。したがって、この関数を直接呼び出すだけで済みます。

に関するより複雑な引数については、こちらをご覧newください 。JavaScriptの「新しい」キーワードは有害と見なされますか?


3
新しいキーワードの使用に問題はありません。私はその周りのすべてのFUDが嫌いです。
スキマ

1
@スキマ同意。:-D私はそれがこの場合問題ではない理由を指摘し、他のnew人がそこでの戦争に参加できるようにするための他の質問にリンクしています。
ブラッド

0

コード例は次のとおりです。

主に

square(width,function (data)
{
   console.log(data.squareVal);
});

以下を使用するとうまくいくかもしれません

exports.square = function(width,callback)
{
     var aa = new Object();
     callback(aa.squareVal = width * width);    
}

0

最後に、NodeはJavascriptについてです。JSには何かを達成するためのいくつかの方法があり、「コンストラクター」を取得するのと同じことです。重要なことは、関数を返すことです

この方法では、たとえばWebブラウザー環境でJSを使用して作成したように、実際には新しい関数を作成しています。

個人的には、Sukimaがこの投稿で提案したように、プロトタイプアプローチを好みます。Node.js-コンストラクターとしてのmodule.exportsの使用

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