我一直在处理JavaScript中的可选参数,如下所示:

function myFunc(requiredArg, optionalArg){
  optionalArg = optionalArg || 'defaultValue';

  // Do stuff
}

有更好的方法吗?

这样使用||会失败吗?


当前回答

我习惯于看到一些处理可选变量的基本变化。有时,轻松的版本很有用。

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

例如,与变量a一起使用的错误默认值在Backbone.js中广泛使用。

其他回答

如果需要插入一个NULL,那么可能会遇到一些问题。除此之外,不,我认为你可能走上了正确的轨道。

有些人选择的另一种方法是使用一个变量的assoc数组在参数列表中迭代。它看起来有点整洁,但我想它有点(非常少)更需要处理/内存。

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

理想情况下,您可以进行重构以传递一个对象并将其与默认对象合并,因此传递参数的顺序无关紧要(请参阅下面的答案第二部分)。

然而,如果你只是想要一些快速、可靠、易于使用且体积不大的东西,请尝试一下:


对任意数量的默认参数的快速修复

它的伸缩性很好:每个新默认值的额外代码最少您可以将其粘贴到任何位置:只需更改所需参数和变量的数量如果您想将undefined传递给具有默认值的参数,那么这种方式会将变量设置为undefineed。此页面上的大多数其他选项将用默认值替换undefined。

下面是一个为三个可选参数(带有两个必需参数)提供默认值的示例

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

简单的演示。这与roenving的答案类似,但很容易扩展到任意数量的默认参数,更容易更新,并且使用的参数不是Function.arguments。


传递和合并对象以提高灵活性

上面的代码和许多默认参数的方法一样,不能按顺序传递参数,例如,传递optionalC,但让optionalB返回默认值。

一个很好的选择是传递对象并与默认对象合并。这也有利于可维护性(只需注意保持代码可读,这样未来的合作者就不会对您传递的对象的可能内容进行猜测)。

使用jQuery的示例。如果不使用jQuery,可以改用Undercore的_.defaults(对象,默认值)或浏览以下选项:

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

这是一个简单的例子。

arg||“默认”是一种很好的方法,适用于90%的情况当您需要传递可能“错误”的值时,它会失败假的0NaN公司""对于这些情况,您需要更加详细地检查未定义的当你首先有可选参数时,也要小心,你必须知道所有参数的类型

这是我的解决方案。使用此选项,您可以保留所需的任何参数。可选参数的顺序并不重要,您可以添加自定义验证。

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });

似乎最安全的方法-在决定使用默认值之前处理所有提供的错误类型的参数-是检查所调用函数中是否存在可选参数。

依赖于arguments对象成员创建(如果缺少参数,甚至不会创建),无论它可能被声明,我们都可以这样编写函数:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

利用此行为:每当我们需要确保函数获得其过程中所需的某个值时,我们都可以安全地检查参数列表中的任何缺失值。

在下面的演示代码中,我们将故意将一个无类型和无值的undefined作为默认值,以便能够确定它是否会在错误的参数值(如0 false等)上失败,或者它的行为是否符合预期。

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

现在,检查几个错误的参数值,看看是否正确检测到它们的存在,并因此计算为真:

argCheck( "", 0, false, null );
>> true true true true

这意味着-它们没有将/识别为预期的参数值。这里我们检查了所有参数的缺失,根据我们的算法,即使它们是假的,也应该获取它们的默认值。

argCheck( );
>> undefined false 0 null

如我们所见,参数arg1、arg2、arg3和未声明的arg4按顺序返回其确切的默认值。因为我们现在已经确定了它的有效性,所以我们可以重写函数,该函数实际上可以像第一个示例中那样使用它们,方法是使用if或三元条件。

对于具有多个可选参数的函数,-循环,可能会为我们节省一些时间。但是,由于如果不提供参数名称的值,则参数名称不会被初始化,因此即使我们以编程方式编写了默认值,我们也无法再通过名称访问它们,因此只能通过参数[索引]访问它们,这对代码的可读性来说是无用的。

但除了在某些编码情况下可能完全可以接受的这种不便之外,还有一个未知的问题,即多个任意数量的参数默认值。这可能也应该被认为是一个错误,因为我们不能再跳过参数,因为我们曾经可以在不提供值的情况下,使用如下语法:

argCheck("a",,22,{});

因为它会扔!这使得我们无法用所需默认值的特定错误类型替换参数。这是愚蠢的,因为arguments对象是一个类似数组的对象,并且应该支持这种语法和约定,无论是原生的还是默认的!

由于这个短视的决定,我们不能再希望编写这样的函数:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

在这种情况下,我们将能够在arguments行中写入所需类型的每个默认值,并且至少能够通过args.index访问它们。

例如,此函数调用将产生:

argCheck();
>>undefined 0 false null

如我们的默认参数值数组中所定义的。但是,仍有可能出现以下情况:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

但遗憾的是:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

否则将记录:

>>a 0 false 22

但那是一个更好的世界!然而,对于最初的问题,最上面的函数会做得很好。例如。:

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

p.s.:很抱歉,在编写参数输入时没有保留所选默认值的类型。