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

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

  // Do stuff
}

有更好的方法吗?

这样使用||会失败吗?


当前回答

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

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


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

它的伸缩性很好:每个新默认值的额外代码最少您可以将其粘贴到任何位置:只需更改所需参数和变量的数量如果您想将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);
}

这是一个简单的例子。

其他回答

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

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


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

它的伸缩性很好:每个新默认值的额外代码最少您可以将其粘贴到任何位置:只需更改所需参数和变量的数量如果您想将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);
}

这是一个简单的例子。

使用ES2015/ES6,您可以利用Object.assign,它可以替换$.exd()或_.defaults()

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

也可以使用默认参数,如下所示

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // 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中广泛使用。

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

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'
        });

如果需要插入一个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];

    // ...
}