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

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

  // Do stuff
}

有更好的方法吗?

这样使用||会失败吗?


当前回答

对undefined的测试是不必要的,也不像可能的那样健壮,因为正如user568458所指出的,如果通过null或false,则提供的解决方案将失败。API的用户可能认为false或null将强制方法避免该参数。

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

结果是:

defaultValue
provided
null
false

最后两个可能很糟糕。相反,请尝试:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

结果是:

defaultValue
provided
defaultValue
defaultValue

唯一一个不理想的情况是,当您实际拥有布尔值或故意为空的可选参数时。

其他回答

如果传递了optionalArg,但计算结果为false,则逻辑将失败-请尝试此选项

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

或者另一个成语:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

使用哪种成语最能传达你的意图!

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

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


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

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

这是一个简单的例子。

这就是我的结局:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

这样调用:

WhoLikesCake({ b : "I do" });

对undefined的测试是不必要的,也不像可能的那样健壮,因为正如user568458所指出的,如果通过null或false,则提供的解决方案将失败。API的用户可能认为false或null将强制方法避免该参数。

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

结果是:

defaultValue
provided
null
false

最后两个可能很糟糕。相反,请尝试:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

结果是:

defaultValue
provided
defaultValue
defaultValue

唯一一个不理想的情况是,当您实际拥有布尔值或故意为空的可选参数时。

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