使用module.exports作为构造函数
根据Node.js手册:
如果您希望模块导出的根是一个函数(如构造函数),或者如果要在一个赋值中导出完整对象而不是一次构建一个属性,请将其分配给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
关键字的问题有一个简单的答案:是的。 我会说明...
模块出口
您可以使用提供的exports
变量将属性附加到它。 一旦在另一个模块中需要这些分配属性就可用。 或者,您可以将对象分配给module.exports属性。 无论哪种情况, require()
返回的内容都是对module.exports
值的module.exports
。
关于如何定义模块的伪代码示例:
var theModule = {
exports: {}
};
(function(module, exports, require) {
// Your module code goes here
})(theModule, theModule.exports, theRequireFunction);
在上面的例子中, module.exports
和exports
是同一个对象。 最酷的部分是,在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"
在我看来,一些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的“新”关键字是否有害?