Javascript 配置为的NodeJS模块-从require或Module.exports实例化
我正在开发一个node.js模块,它有几个功能。Javascript 配置为的NodeJS模块-从require或Module.exports实例化,javascript,node.js,Javascript,Node.js,我正在开发一个node.js模块,它有几个功能。 模块本身将需要一些配置来启动(将有默认值…可以覆盖-例如文件路径) 导出函数时首选的方法是什么? 允许从require语句实例化它,并将配置对象(可选)传递给构造函数 var MyModule = require('myModule); var myModule = new MyModule({ name: "test name" }); myModule.doThing(function(x){ }); 在模块中包含以下内容:
模块本身将需要一些配置来启动(将有默认值…可以覆盖-例如文件路径) 导出函数时首选的方法是什么? 允许从require语句实例化它,并将配置对象(可选)传递给构造函数
var MyModule = require('myModule);
var myModule = new MyModule({
name: "test name"
});
myModule.doThing(function(x){
});
在模块中包含以下内容:
module.exports = function MyModule(){
MyModule.prototype.config = {name: "default name"}
function doThing(cb){
//do stuff
cb();
}
}
module.exports = exports = MyModule();
function MyModule(){
MyModule.prototype.config = {name: "default name"}
function doThing(cb){
//do stuff
cb();
}
}
或者,从模块中的exports语句创建一个实例,然后像这样使用它:
var myModule = require('myModule);
myModule.config = {name: "test name"}
myModule.doThing(function(x){
});
相反,在模块中包含以下内容:
module.exports = function MyModule(){
MyModule.prototype.config = {name: "default name"}
function doThing(cb){
//do stuff
cb();
}
}
module.exports = exports = MyModule();
function MyModule(){
MyModule.prototype.config = {name: "default name"}
function doThing(cb){
//do stuff
cb();
}
}
我会说,让用户在实例化时提供一个对象,将默认值放在原型中。您可能还希望提供配置功能,这允许您(现在或将来)验证密钥/值,并且您的用户可以在实例化后设置配置
// Module
var Mod = module.exports = function Mod (opts) {
opts = (opts === Object(opts)) ? opts : {};
// This allows users to instanciate without the `new` keyword
if (! (this instanceof Mod)) {
return new Mod(opts);
}
// Copy user provided configs to this.config
for (var key in opts) if ({}.hasOwnProperty.call(opts, key)) {
this.config[key] = opts[key];
}
};
Mod.prototype.config = {
foo : 'foo',
bar : 'bar'
};
Mod.prototype.configure = function configure (key, val) {
this.config[key] = val;
return this;
};
// Usage
const Mod = require('/path/to/mod');
var i1 = new Mod;
var i2 = Mod();
var i3 = new Mod({
foo: 'bar'
});
var i4 = Mod({
foo: 'bar'
});
i4.configure('bar', 'baz');
var i5 = (new Mod).configure('bar', 'baz');
编辑
正如Jake Sellers在评论中指出的,这不是CommonJS模块中的标准API模式。
更好的解决方案是导出一个函数,该函数返回您正在创建的任何对象
更重要的是,我不建议将配置放在原型中。这样做会使配置对象被所有子对象共享。因此,对它的任何修改也将影响所有儿童。真可耻,我写这篇废话的时候还不是初学者。多谢,杰克;)
更好的实施:
// Keep defaults private
var defaults = {
foo : 'foo',
bar : 'bar'
};
// Construct
var Mod = function Mod (opts) {
opts = (opts === Object(opts)) ? opts : {};
// This allows users to instanciate without the `new` keyword
if (! (this instanceof Mod)) {
return new Mod(opts);
}
this.config = {};
// Copy user provided configs to this.config or set to default
for (var key in defaults) if (defaults.hasOwnProperty(key)) {
if ({}.hasOwnProperty.call(opts, key)) {
this.config[key] = opts[key];
}
else {
this.config[key] = defaults[key];
}
}
};
// Let the user update configuration post-instanciation
Mod.prototype.configure = function configure (key, val) {
this.config[key] = val;
return this;
};
// Export a function that creates the object
exports.createMod = function createMod (opts) {
return new Mod(opts);
};
// Export the constructor so user is able to derive from it
// or check instanceof
exports.Mod = Mod;
// USAGE
var mod = require('/path/to/mod');
var i1 = mod.createMod({ foo : 'bar' });
i1.configure('bar', 'baz');
这取决于您是否希望模块的用户能够恰好使用一个预定义实例(即您在
module.exports
上创建的实例),或者您是否希望他们能够创建自己的实例(然后您需要将构造函数作为函数导出,而不是其返回值)
如果你去写一个构造函数,我会选择第二个选项(让用户创建实例)——除非它是你提供的单例对象。真的是这样。i1和i2之间的区别是什么?实际上,第7-9行没有确保,如果用户不实例化,而只是像函数一样调用构造函数,我们就为他实例化。第7行检查此是否是新创建的
Mod
实例,如果不是,第8行创建并返回一个实例,将用户提供的配置传递给构造函数,因此它具有完全相同的效果。我想我明白了。我还有一个相关的问题(虽然超出了这个问题的范围)-什么?您仍在调用require,然后调用new
或构造函数。。。这不是npm所需的任何模块的使用方式……对,这不是标准模式。我不是自己做的。由于问题中缺少语义信息,我提出这个解决方案是为了接近Alex实现。我用一般性的注释编辑过。