Node.js – 使用module.exports作为构造函数

根据Node.js手册:

如果您希望模块导出的根目录是一个函数(如构造函数),或者如果要在一个赋值中导出一个完整的对象,而不是一次构build一个属性,则将其分配给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模块允许两种方式来定义导出的属性。 无论哪种情况,您都要返回一个对象/函数。 因为函数是JavaScript中的一等公民,所以它们可以像对象一样行事(技术上它们是对象)。 这就是说你使用new关键字的问题有一个简单的答案:是的。 我会说明…

模块出口

您可以使用提供的exportsvariables来附加属性。 一旦在另一个模块中需要这些分配属性变为可用。 或者你可以分配一个对象到module.exports属性。 在任何一种情况下, require()返回的值都是对module.exports值的module.exports

如何定义模块的伪代码示例:

 var theModule = { exports: {} }; (function(module, exports, require) { // Your module code goes here })(theModule, theModule.exports, theRequireFunction); 

在上面的例子中, module.exportsexports是同一个对象。 最酷的部分是,在CommonJS模块中没有看到任何这样的模块,因为整个系统需要处理所有你需要知道的是有一个模块对象具有一个exports属性和一个exportsvariables指向与module.exports一样的东西。

需要与构造函数

既然你可以直接附加一个函数到module.exports你可以基本上返回一个函数,就像任何函数一样,它可以作为一个构造函数来pipe理(这是斜体,因为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; } }; } 

调用square时不需要new关键字。 你不是从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); }