当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《有没有更好的方法在JavaScript中执行可选的函数参数?》经验,为你挑选了10个好方法。

我总是在JavaScript中处理可选参数,如下所示:

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

  // Do stuff
}

有没有更好的方法呢?

是否有任何使用||这种情况会失败的情况?



1> Paul Dixon..:

如果传递了OptionalArg,您的逻辑将失败,但评估为false - 请尝试将此作为替代方法

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

或另类成语:

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

使用哪个成语最能传达您的意图!


我使用三等于('... lArg ==="und ...')是安全的.
为什么在这里使用三元运算符?是不是第二个条款只设置optionalArg = optionalArg?.我认为只需要一个简单的IF:if(typeof optionalArg ==="undefined")optionalArg ="defaultValue";
最好使用===习惯,这样你就不必记住在哪种情况下它是"安全的".
我认为它更好地表明了意图 - typeof不评估操作,只检查它的类型,这是我们感兴趣的.而且,评估将慢大约40%(http://jsperf.com/stackoverflow148901)
好吧,你不是在谈论可选参数 - 你真的*是*传递参数,所以这个解决方案不适用于你的情况.NaN并不意味着"未定义" - 这意味着你传递了一个数字,但它的值是NaN.有关更多信息,请参见http://stackoverflow.com/questions/3215120/why-javascript-says-that-a-number-is-not-a-number
@PaulDixon只是好奇,随着时间的推移,基准测试结果已经倒置(自Chrome 31以来)http://jsperf.com/stackoverflow148901似乎Chrome开发人员已经优化了更常用的方法
为什么要使用typeof?`optionalArg =(optionalArg === undefined)?"defaultValue":optionalArg;`
由于typeof返回一个字符串,因此在类型检查时不需要@Jarrod ===,但这样做没有任何危害.

2> 小智..:

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

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

在这篇关于MDN的文章中更多关于它们(尽管文章标题,它们在JavaScript中被称为"参数"而不是"参数").

目前仅支持Firefox,但随着标准的完成,预计支持将迅速提升.


这对我来说足够证明,JavaScript确实是邪恶的.@ThoAppelsin
JavaScript对那些不理解它的人来说是邪恶的(不是说你没有,但这是我的看法).我认为它的范式在概念上非常强大(实现一直在变得更好).
哦,你好Python语法.很高兴再见到你.
@HubertGrzeskowiak同样适用于许多其他语言,不仅仅是Python或C#:)这是默认参数值的常用方法.
@HubertGrzeskowiak和C#语法(默认值,如果没有别的).
由于ES6是当前的标准,这是正确的答案.

3> trusktr..:

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

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

Paul Dixon的回答(以我的拙见)不如此可读,但归结为偏好.

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

编辑11/17/2013 9:33 pm:我已经为Node.js创建了一个包,它可以更容易地"重载"称为参数的函数(方法).


+1,但是typeof返回一个字符串,所以你需要在undefined周围加上引号才能工作:`if(typeof myVariable =="undefined")`...
我做了这个答案,并接受了答案,战斗到死.对于我运行的一些测试,接受者答案的三元方法稍慢:http://jsperf.com/optional-function-parameters-ternary-vs-manual

4> Oli..:

如果您需要查看文字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"?

5> user56reinst..:

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

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


对任意数量的默认参数进行干净的快速修复

它优雅地扩展:每个新默认值的最小额外代码

您可以将其粘贴到任何位置:只需更改所需的参数和变量的数量

如果要传递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的答案,但可以轻松扩展为任意数量的默认参数,更容易更新,并且不使用argumentsFunction.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);
}

这是一个简单的例子.


我不确定我每秒钟会调用2360万次操作......确实'typeof`速度非常快,但这并不会让`switch`变慢 - 只是不那么快.

6> roenving..:

你可以使用一些不同的方案.我一直在测试arguments.length:

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

- 这样做,它不可能失败,但我不知道你的方式是否有任何失败的机会,只是现在我想不出一个场景,它实际上会失败...

然后保罗提供了一个失败的场景! - )


什么是"一个失败的场景"?如果传递false,null,0等,则不会更改arguments数组的长度.否则,使用此开关(myFunc.arguments.length)是好的和灵活的.

7> Jonny Buchan..:

与Oli的答案类似,我使用一个参数Object和一个定义默认值的Object.带点糖......

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

......这可以做得更好一些.

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

这种方法有什么好处?

您可以省略任意数量的参数 - 如果您只想覆盖一个参数的值,您可以只提供该参数,而不必显式传递undefined,比如说有5个参数而您只想自定义最后一个参数一,就像你建议的其他一些方法一样.

当使用构造函数函数从一个继承自另一个的对象时,很容易接受您继承的对象的构造函数所需的任何参数,因为您不必在构造函数签名中命名这些参数,或者甚至提供你自己的默认值(让父对象的构造函数为你做这个,如上面CharField调用Field的构造函数所示).

继承层次结构中的子对象可以根据需要自定义其父构造函数的参数,强制执行它们自己的默认值或确保始终使用某个值.



8> Vitim.us..:

如果你广泛使用默认值,这似乎更具可读性:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

只需在全局escope上声明此函数即可.

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

使用模式 fruit = defaultValue(fruit,'Apple');

*PS你可以将defaultValue函数重命名为一个简短的名称,只是不要使用default它是javascript中的保留字.



9> Petr Hurtak..:

宽松的类型检查

容易写,但是0,'',false,nullundefined将被转换为默认值,这可能不是期望的结果.

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

严格的类型检查

更长,但涵盖了大多数情况.只有错误地指定默认值的情况才是我们undefined作为参数传递的情况.

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

检查参数变量

捕获所有案例,但写起来最笨拙.

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

不幸的是,目前浏览器支持很差

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

}



10> Yann Bertran..:

使用ES2015/ES6,您可以利用Object.assign哪些可以替代$.extend()_.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
}

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有