可变长度参数的Javascript约定

时间:2012-03-06 20:27:56

标签: javascript coding-style

我正在进行更多javascript开发,并希望确保我遵循流行的约定。 目前我有一个库,它包含可以传递1个模型进行操作的函数,或者许多模型。

鉴于一些javascript库很受欢迎的气候,我很好奇;通过枚举参数变量,或者允许其中一个参数成为数组,我会通过实现我的'单项或列表'要求来符合'事实标准'吗?

场景1:参数枚举

// passing a single entity to my function
sendMail( email, recipient1 );

// passing multiple entities to my function
sendMail( email, recipient1, recipient2 );

场景2:实体参数是单个实例,或数组

// pass a single entity
sendMail( email, recipient1 );

// passing multiple entities
sendMail( email, [recipient1, recipient2] );

我看过使用“场景2”的jQuery领域,但我还是想问一下 - 哪种方法最受欢迎,为什么?

由于

[编辑]

一些注释遵循同样的方式,使用一个参数对象 - 类似于'场景2' - 但我觉得它引入了不必要的复杂性 - 元素不需要命名,因为它们只是一个变量长度清单。我想我会在这里添加一下,以防我的问题不够明确。

[编辑]

我通过jQuery-1-7.js

看到这样的代码
queue: function( elem, type, data ) {
    var q;
    if ( elem ) {
        type = ( type || "fx" ) + "queue";
        q = jQuery._data( elem, type );

        // Speed up dequeue by getting out quickly if this is just a lookup
        if ( data ) {
            if ( !q || jQuery.isArray(data) ) {
                q = jQuery._data( elem, type, jQuery.makeArray(data) );
            } else {
                q.push( data );
            }
        }
        return q || [];
    }
}

[编辑]

在与JP讨论之后,我提出了这个 - 我不是说这是正确的选择,但它非常灵活......

lastArgumentAsParams: function()
{
    var callerArgs = jQuery.makeArray(this.lastArgumentAsParams.caller.arguments);

    // return empty set if caller has no arguments
    if ( callerArgs.length == 0 )
        return [];
     callerArgs.splice(0, callerArgs.length - 1)
    // remove all but the last argument
    if ( callerArgs.length == 1 && jQuery.isArray(callerArgs[0]))
        return callerArgs[0];
    else
        return callerArgs;
}

如果在任何函数的开头调用此函数 - 它会将调用者中的最后一个arg视为“可变长度参数” - 支持任何约定。

例如,我可以像这样使用它

function sendEmail( body, recipients )
{
    recipients = lastArgumentAsParams();

    // foreach( recipient in recipients )...
}

现在,我可以通过以下任何方式调用'sendEmail',它将按预期工作

sendEmail('hello world', "bill@microsoft.com" );
sendEmail('hello world', "bill@microsoft.com", "steve@apple.com" );
sendEmail('hello world', ["bill@microsoft.com", "steve@apple.com"] );

3 个答案:

答案 0 :(得分:7)

我个人更喜欢使用对象文字作为参数来支持命名参数,如下所示:

var myfunc = function(params){ //same as: function myfunc(params){....
  alert(params.firstName);
  alert(params.lastName);   
};

myfunc({firstName: 'JP', lastName: 'Richardson'});

我认为它使代码非常易读,顺序无关紧要。

您还可以访问arguments对象。注意,它不是一个数组,但它是“类似数组”。您可以在此处阅读:http://javascriptweblog.wordpress.com/2011/01/18/javascripts-arguments-object-and-beyond/

修改

你似乎在这里有误解。您正在使用短语“arguments object”,并且认为它与对象文字符号相同。他们不是。

arguments对象允许您执行此操作:

function myfunc(){
  alert(arguments[0]); //JP
  alert(arguments[1]); //Richardson 
}

myfunc('JP', 'Richardson');

这有帮助吗?

答案 1 :(得分:2)

另一种常见方法是使用object literal作为变量:

myFunction(true, {option: value, option2: value});

我个人更喜欢这种方法,因为它更冗长,并且使用javascript松散类型,它可以为您提供更好的提示,并忽略顺序。

Backbone.js正在使用它作为首选方法。

答案 2 :(得分:2)

为了扩展其他答案,我通常会看到两个主要的替代方案:可选参数和关键字参数。我不记得看到“数组使用”这个习惯用法的任何好例子,而且考虑到arguments数组总是可用,它有点过时了。

无论如何,我的经验法则是。

  • 如果我有很多参数,或者参数列表可能会更改,或者参数没有良好的自然顺序,使用命名参数模式

    我最喜欢这种风格的部分是它非常灵活且面向未来,同时也是一种自我记录(以小型风格)。

    foo({x1:'1', x2:'2', x3:'3'});
    
    function foo(kwargs){
        //I try to always copy the arguments back into variables.
        //Its a little verbose but it helps documentation a lot and also
        // lets me mutate the variables if I want to
    
        var x1 = kwargs.x1,
            x2 = kwargs.x2,
            x3 = kwargs.x3;
    }
    
  • 如果我的参数很少,不太可能改变,并且对它们有自然的顺序,使用普通函数(在命令中最后一个可选参数)

    foo(x1, x2);
    foo(x1, x2, x3);
    

    我现在可以想到如何处理函数中的可选参数有三个主要变体:

    var foo = function(x1, x2, x3){
    
         //variation 1: truthy/falsy
         // Short, but I tend to only use it when the variable stands
         // for an object or other always-truthy kind of value
         x3 = x3 || 'default_value';
    
         //variation 2: using a special placeholder value for blank arguments.
         // Usually this is null or undefined. (and undefined works if the arg is not passed too)
         if(typeof x3 === 'undefined'){ x3 = 'default_value'; }
    
         //variation 3: explicitly check the number of arguments
         // I really like this one since it makes clear if the argument was passed or not.
         if(arguments.length < 3){ x3 = 'default_value'; }
    }
    

此外,还有一些我试图避免的事情:

  • 不要拥有接收大型参数列表的函数。如果它们开始成为可选项并且您忘记了订单,它就会变得一团糟

    foo(1, 2, null, null, 3, null, null); //ugh
    
  • 不要使用固定长度数组是棘手的。它们是多余的,没有任何数组,当我看到一个数组时,我通常期望它1)是同质的,2)能够只要我想要

    foo(true, [1, 2]); //should be foo(true, 1, 2)