有没有更好的方法在 JavaScript 中做可选的函数参数?

IT技术 javascript function arguments
2021-01-18 05:58:08

我总是像这样在 JavaScript 中处理可选参数:

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

  // Do stuff
}

有没有更好的方法来做到这一点?

有没有||像这样使用会失败的情况?

6个回答

如果通过 optionalArg,您的逻辑将失败,但评估为 false - 试试这个作为替代

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

或者另一种习语:

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

使用最能向您传达意图的习语!

最好养成使用 === 的习惯,这样您就不必记住在哪种情况下它是“安全的”。
2021-03-17 05:58:08
为了安全起见,我会使用三重等于 ('...lArg === "und...')。
2021-03-23 05:58:08
我认为它更好地表明了意图 - typeof 不评估操作,只检查它的类型,这是我们感兴趣的。此外,评估会慢 40% 左右(jsperf.com/stackoverflow148901
2021-03-23 05:58:08
好吧,您不是在谈论可选参数 - 您实际上是在传递参数,因此此解决方案不适用于您的情况。NaN 并不意味着“未定义”——它意味着你传递了一个数字,但它的值为 NaN。有关更多信息,请参见stackoverflow.com/questions/3215120/...
2021-04-08 05:58:08
为什么在这里使用三元运算符?第二个子句不是只是设置 optionalArg = optionalArg 吗?。我认为只需一个简单的 IF 即可: if(typeof optionalArg === "undefined") optionalArg = "defaultValue";
2021-04-09 05:58:08

ECMAScript 2015(又名“ ES6 ”)中,您可以在函数声明中声明默认参数值:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

在 MDN 上的这篇文章中有更多关于它们的信息

目前仅 Firefox 支持,但随着标准的完成,预计支持会迅速改进。


编辑(2019-06-12):

现代浏览器现在广泛支持默认参数。并非
所有版本的 Internet Explorer都不支持此功能。但是,ChromeFirefoxEdge目前支持它。

哦,你好 Python 语法。很高兴再见到你。
2021-03-22 05:58:08
JavaScript 只对那些不理解它的人有害(不是说你不理解,但这是我的观点)。我认为它的范式在概念上非常强大(实现一直在变得更好)。
2021-03-29 05:58:08
@HubertGrzeskowiak 同样适用于许多其他语言,而不仅仅是 Python 或 C# :) 默认参数值是一种相当常见的方法。
2021-03-31 05:58:08
由于 ES6 是当前标准,这是正确的答案。
2021-04-01 05:58:08
这对我来说足以证明 JavaScript 确实是邪恶的。@ThoAppelsin
2021-04-09 05:58:08

我发现这是最简单、最易读的方式:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

保罗迪克森的回答(以我的拙见)比这更难读,但这归结为偏好。

insin 的答案要先进得多,但对大功能更有用!

编辑 2013 年 11 月 17 日下午 9:33:我为 Node.js 创建了一个包,它可以更轻松地“重载”称为参数的函数(方法)

我做了这个答案,以及接受的答案,战斗到死。对于我运行的少数测试,接受者答案的三元方法稍慢:jsperf.com/optional-function-parameters-ternary-vs-manual
2021-03-29 05:58:08
@OmShankar 没有区别。
2021-03-30 05:58:08
+1,但 typeof 返回一个字符串,因此您需要在 undefined 周围加上引号才能使其工作:if(typeof myVariable == "undefined")...
2021-04-10 05:58:08

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

有些人选择的另一种方法是采用一个关联的变量数组,遍历参数列表。它看起来更整洁,但我想它有点(非常少)更多的进程/内存密集型。

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];

    // ...
}
为什么不是 hasOwnProperty 而不是 == "undefined" ?
2021-03-16 05:58:08
为什么不if (!(i in argArray))呢?为了完整if起见,在此 -语句之前,应该检查正确的参数类型,例如if (typeof argArray !== "object") argArray = [];.
2021-03-29 05:58:08

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

但是,如果您只想要快速、可靠、易于使用且不笨重的东西,请尝试以下操作:


任何数量的默认参数的干净快速修复

  • 它优雅地扩展:每个新默认值的额外代码最少
  • 您可以将其粘贴到任何地方:只需更改所需参数和变量的数量
  • 如果要传递undefined给具有默认值的参数,这样,变量将设置为undefined. 此页面上的大多数其他选项将替换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's answer,但很容易扩展为任意数量的默认参数,更容易更新,并且使用argumentsnotFunction.arguments


传递和合并对象以获得更大的灵活性

上面的代码,像许多处理默认参数的方法一样,不能乱序传递参数,例如,传递optionalC但离开optionalB以回退到其默认值。

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

使用 jQuery 的示例。如果您不使用 jQuery,则可以改用 Underscore_.defaults(object, defaults)浏览以下选项

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

是它一个简单示例

嘿,这是我见过的最干净的方式。唯一的问题是:jsperf.com/optional-parameters-typeof-vs-switch 开关显然很慢..
2021-03-24 05:58:08
不确定我是否会称每秒 2360 万次操作很慢……这确实typeof快得令人难以置信,但这并不会switch变慢——只是没有那么快。
2021-03-25 05:58:08
不确定我是否理解这一点。当参数实际给出时,它不会也替换值吗?!
2021-04-06 05:58:08