在 Javascript 中允许命名参数或位置参数

Allow either named arguments or positional arguments in Javascript

如何让函数接受 或者 命名参数 (foo({a: 'hello', b: 'it is me'})) 位置参数 (foo('hello', 'it is me'))?

我知道可以通过将对象传递给函数来模拟命名参数:

function foo(options) {
    options = options || {};
    var a = options.a || 'peanut'; // whatever default value
    var b = options.b || 'butter'; // whatever default value
    console.log(a, b);
}

// ES6 allows automatic destructuring
function foo({a = 'peanut', b = 'butter'} = {}) {
    console.log(a, b);
}

但这不允许我接受要传递的位置参数。

我想使用 ES6,但 ES5 的任何东西都可以。

我想这样的事情会奏效:

function foo(...options){
   if (typeof options[0] === 'object'){
    console.log('expect object', options[0]);
  }else{
    console.log('expect array', options);  
  }
}

foo('peanut', 'butter');
foo({a:'peanut', b:'butter'});

我认为没有为此内置的东西,但这段代码应该适合你的情况

function foo({a = 'peanut', b = 'butter'} = {}) {
    if (typeof arguments[0] === 'string') {
        return foo({a: arguments[0], b: arguments[1]})
    }
    console.log(a, b);
}

首先,我真的会建议坚持使用一种方法。正如你所说,使用 either "named"

function foo({a = 'peanut', b = 'butter'} = {}) {
    console.log(a, b);
}

位置参数:

function foo(a = 'peanut', b = 'butter') {
    console.log(a, b);
}

选择更适合您的功能,不要混用


如果您出于某种原因确实需要两者,standard overloading techniques 可供您使用。只有当您的第一个位置参数不是对象时,它才会正常工作。我会提出以下成语之一:

function foo(a, b) { // positional is normal case
    if (arguments.length == 1 && typeof arguments[0] == "object")
        {a, b} = arguments[0];

    console.log(a, b);
}
function foo({a, b}) { // named is normal case
    if (arguments.length > 1 || typeof arguments[0] != "object")
        [a, b] = arguments;

    console.log(a, b);
}

如果您需要默认值,无论哪种方式都会变得丑陋:

function foo(a, b) {
    var opts = (arguments.length == 1 && typeof arguments[0] == "object")
      ? arguments[0]
      : {a, b};
    ({a = 'peanut', b = 'butter'} = opts);

    console.log(a, b);
}