Node.jsマニュアルによると:
モジュールのエクスポートのルートを関数(コンストラクターなど)にしたい場合、または一度に1つのプロパティを作成するのではなく、1つの割り当てで完全なオブジェクトをエクスポートする場合は、exportsではなく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());
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.exports
とexports
は同じオブジェクトです。クールな部分は、システム全体がそれを処理するため、CommonJSモジュールには何も表示されないということです。exportsプロパティと、それを指すexports変数を持つモジュールオブジェクトがあることを知っておく必要があります。 module.exportsと同じこと。
関数をmodule.exports
に直接アタッチできるため、基本的に関数を返すことができ、他の関数と同様にconstructorとして管理できます(関数と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"
私の意見では、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
キーワードを使用してインスタンス化します。他のすべては同じままです。
この質問は、require()
の動作とは関係ありません。基本的に、モジュールでmodule.exports
に設定したものは、それに対するrequire()
呼び出しから返されます。
これは次と同等です:
var square = function(width) {
return {
area: function() {
return width * width;
}
};
}
new
を呼び出すときに、square
キーワードは必要ありません。 square
から関数インスタンス自体を返すのではなく、最後に新しいオブジェクトを返します。したがって、この関数を直接呼び出すことができます。
new
をめぐるより複雑な引数については、これを確認してください。 JavaScriptの「新しい」キーワードは有害と考えられますか?
サンプルコードは次のとおりです。
主に
square(width,function (data)
{
console.log(data.squareVal);
});
以下を使用するとうまくいくかもしれません
exports.square = function(width,callback)
{
var aa = new Object();
callback(aa.squareVal = width * width);
}
最後に、NodeはJavascriptに関するものです。 JSには何かを達成するためのいくつかの方法があり、「コンストラクタ」を取得するのと同じことです。重要なことは関数を返すことです。
この方法では、たとえば、Webブラウザー環境でJSを使用して作成したように、実際に新しい関数を作成しています。
個人的には、この投稿でSukimaが示唆したように、プロトタイプのアプローチを好みます: Node.js-コンストラクターとしてのmodule.exportsの使用