构buildnode.js中需要的库的最佳实践
我有几个实用程序库,其中包含帮助函数,我想加载它们,以便他们可以从控制器使用,我想知道在节点中编码实用程序库的最佳做法是什么。
我有点困惑,因为有几种方法来做到这一点,我不知道什么是最好/更合适/更可靠。 这里有2个选项,但我想知道,如果他们是最好的(例如,我已经看到使用module.exports = exports = function(){}
等片段)
//option1.js
"use strict"; module.exports = function(){ exports.test1 = function(){ console.log('hi I'm test1')}; exports.test2 = function(){ console.log('hi I'm test2')}; return exports; };
//option2.js
"use strict"; module.exports = { test1 : function(){ console.log('soy test1')}, test2 : function(){ console.log('soy test2')} };
//test_controller.js
/* Requiring helpers in different ways */ var option1 = require('./option1.js')(); var option2 = require('./option2.js');
我想我的文件在三个部分:
第1节:CommonJS依赖
var lib1 = require("lib1"); var lib2 = require("lib2");
你不需要任何额外的包装函数。 所有的节点模块都被node.js 自动包装在一个函数中,这样做没有任何好处,只是增加了混乱
第2节:普通的JavaScript代码
如果需要的话,这应该几乎完全是function齐备的支持variables或顶级模块代码。
var MY_CONST = 42; function helper1() { //excellent code here } function helper2() { //excellent code here }
保留第2节纯JS。 在这个中间的“纯”部分不要使用commonJS成语。 不要使用module
, exports
, require
等等。这只是我个人的指导方针,因为JS本身是稳定的,但是对模块的封装仍然有很大的改变,最好保持CommonJS位是无关紧要的,并且可能会改变与有趣的代码分离。 ECMAScript 6模块最有可能在几年内取代CommonJS,因此,通过保留第2节纯ECMAScript 5并制作一个“CommonJS Sandwich™”,就像我喜欢的那样,让自己更容易。
第3节:CommonJS出口
exports.helper1 = helper1; exports.helper2 = helper2;
- 把所有的出口放在最后也可以让你快速了解你的公共API是什么,并防止由于不小心的复制/粘贴而意外导出属性。
- 我更喜欢上面的
exports.foo = foo;
语法,而不是将module.exports
分配给新的对象文字。 我发现这避免了与对象文字的最后一个属性的尾随逗号问题。 - 做你
require
或exports
陈述的任何事情几乎肯定是不必要的,不必要的光滑或魔术。 直到你被推进,在这里不要做任何事情。 (即使如此,如果你不是TJ Holowaychuk,你可能只是愚蠢的)
我应该输出什么
单个函数(@substack样式)
function degreesToRadians(degrees) {} module.exports = degreesToRadians;
保持小而简单。
function的一个对象
如果您的模块是一组辅助函数,则应该将包含这些函数的对象导出为属性
var foo = require("foo"); function doubleFoo(value) { return foo(value) * 2; } function tripleFoo(value) { return foo(value) * 3; } exports.doubleFoo = doubleFoo; exports.tripleFoo = tripleFoo;
一个构造函数
如果您的模块是面向对象使用的类devise,则导出构造函数
function GoCart() { this.wheels = 4; } GoCart.prototype.drive = function drive() { //vroom vroom } module.exports = GoCart;
工厂/configurationclosuresfunction
一旦你掌握了上述2种模式(真的!),并且感到有信心导出一个需要select的工厂函数,也许还有其他一些dynamic的东西,那就去做吧,但是如果有疑问的话,坚持前两个更简单的select。
//do-stuff.js function doStuff(howFast, what) { return "I am doing " + what + " at speed " + howFast; } function setup(options) { //The object returned by this will have closure access to options //for its entire lifetime return {doStuff: doStuff.bind(null, options.howFast)}; } module.exports = setup;
所以你可以用这个
var doStuff = require("./do-stuff")({howFast: "blazing speed"}); console.log(doStuff.doStuff("jogging")); //"I am doing jogging at speed blazing speed"
对于无状态的实用程序库, option2.js是要走的路,因为不需要每次require
时require
执行module.exports
的代码,这是在调用require('./option1.js')()
时会发生的情况require('./option1.js')()
使用option1.js 。
另一方面,如果你的模块暴露了创build保持状态的对象的构造函数,那么你会想要option1.js 。 例如,
person.js:
module.exports = function(firstName,lastName){ this.firstName = firstName; this.lastName = lastName; };
然后使用它:
var Person = require("./person"); var person1 = new Person("Foo","Bar"); var person2 = new Person("Joe","Shmoe");
option1.js的另一个优点是(如上所示),它可以让你传递参数到模块中。