在Node.js中,由于多种原因,习惯/推荐将回调函数作为最后一个参数传递给函数.可能还有一个或多个可选参数,我们希望在回调之前传递这些参数.您最终会看到许多非常重复的代码,例如
// receiveMessages([options],[callback]) function receiveMessages(options,callback) { if(typeof options === 'function'){ callback = options; options = {}; // or some other sensible default } //... }
// through([dest],[options],[callback]) function through(dest,options,callback) { if(typeof dest === 'function'){ callback = dest; dest = noop(); options = {}; }else if(typeof options === 'function'){ callback = options; options = {}; } // ... }
解决方法
我想到的一件事是方法重载.从技术上讲,这在JavaScript中不受支持,但有一些方法可以实现这样的事情. John Resig在他的博客中有一篇关于它的文章:
http://ejohn.org/blog/javascript-method-overloading/
另外,这是我的实现,它与John Resig非常相似,并且受到它的高度启发:
var createFunction = (function(){ var store = {}; return function(that,name,func) { var scope,funcs,match; scope = store[that] || (store[that] = {}); funcs = scope[name] || (scope[name] = {}); funcs[func.length] = func; that[name] = function(){ match = funcs[arguments.length]; if (match !== undefined) { return match.apply(that,arguments); } else { throw "no function with " + arguments.length + " arguments defined"; } }; }; }());
createFunction(window,"doSomething",function (arg1,arg2,callback) { console.log(arg1 + " / " + arg2 + " / " + callback); }); createFunction(window,callback) { doSomething(arg1,null,callback); });
这段代码定义了一个全局函数doSomething,一次有三次,一次有两个参数.如你所见,这种方法的第一个缺点是你必须提供一个附加函数的对象,你不能只说“在这里定义一个函数”.此外,函数声明比以前复杂一点.但是现在可以使用不同数量的参数调用函数,并在不使用重复if..else结构的情况下获得正确的结果:
doSomething("he",function(){}); //he / null / function(){} doSomething("he","ho",function(){}); //he / ho / function(){}
到目前为止,只有参数的数量很重要,但我可以考虑扩展它,以便对不同的数据类型做出反应,这样人们也可以区分以下内容:
function doSomething(opt1,opt2,callback){ //some code } doSomething({anObject: "as opt1"},function(){}); doSomething("a string as opt2",function(){});
然而,这可能不是最好的方法,但在某些情况下它可以很方便.对于很多可选参数,我个人喜欢Pumbaa80将这些选项放在一个必需的对象参数中的答案.