DRYing JavaScript函数采取可选参数和回调

在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, "doSomething", function (arg1, 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将这些选项放在一个必需的对象参数中的答案。


在Node.js中,出于多种原因,习惯/推荐将回调传递给作为最后一个参数的函数

我能想到的唯一原因是迫使开发者提供其他论点。

例如, function (success, error)会导致编程不顺畅,因为延迟编码器会简单地省略error回调。 这就是为什么你通常看到function (error, success)

话虽如此,上述公约对强制性论据来说是很好的。 如果你想要可选参数,就不要那样做。 处理这种情况的一种方法是以下方案:

function (required1, required2, ..., callback, options)
// or
function (required1, required2, ..., options, callback)

其中每个可选参数可以或不可以作为options的属性options

编辑 :实际上,这用于某些节点库,例如http://nodejs.org/api/fs.html#fs_fs_appendfile_filename_data_options_callback

链接地址: http://www.djcxy.com/p/72479.html

上一篇: DRYing up JavaScript functions taking optional arguments and a callback

下一篇: storage for aligned allocation of memory blocks