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

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

  // 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中广泛使用。

其他回答

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

你可以使用一些不同的方案。我一直在测试争论。长度:

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

  ...

--这样做,它不可能失败,但我不知道你的方式是否有失败的机会,刚才我想不出一个场景,它实际上会失败。。。

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

使用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中广泛使用。

与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个参数,并且您只想自定义最后一个参数,则必须使用其他建议的方法。当为从另一个继承的对象使用构造函数Function时,很容易接受所继承对象的构造函数所需的任何参数,因为您不必在构造函数签名中命名这些参数,或者甚至提供自己的默认值(让父对象的构造函数为您实现,正如上面CharField调用Field的构造函数时所看到的那样)。继承层次结构中的子对象可以根据需要为其父构造函数自定义参数,强制使用自己的默认值或确保始终使用某个值。