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

时间:2020-03-06 14:52:36  来源:igfitidea点击:

我一直像这样处理JavaScript中的可选参数:

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

  // Do stuff
}

有更好的方法吗?

在任何情况下使用这样的||都会失败吗?

解决方案

如果传递了optionalArg,逻辑将失败,但是评估为false,请尝试使用此方法

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

或者另一种习语:

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

使用任何一种最能传达我们意图的习语!

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

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

  ...

-这样做可能不会失败,但是我不知道方式是否有失败的机会,只是现在我还无法想到一个实际会失败的情况...

然后,保罗提出了一个失败的方案!-)

如果我们需要插入字面量为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];

    // ...
}

与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)

这种方法有什么好处?

  • 我们可以根据需要忽略任意多个参数-如果我们只想覆盖一个参数的值,则可以只提供该参数,而不必在有5个参数且我们只想覆盖的情况下显式传递undefined。自定义最后一个方法,就像我们需要使用其他建议的方法一样。
  • 当使用从另一个对象继承的对象的构造函数时,很容易接受我们要继承的对象的构造函数所需要的任何参数,因为我们不必在构造函数签名中命名这些参数,甚至提供我们自己的默认值(让父对象的构造函数为我们完成此操作,如上CharField调用Field的构造函数所示)。
  • 继承层次结构中的子对象可以为其父构造函数自定义其自定义参数,以强制执行其自己的默认值或者确保始终使用特定值。