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

允许Javascript中的命名参数或位置参数,javascript,parameter-passing,ecmascript-6,Javascript,Parameter Passing,Ecmascript 6,如何让函数接受命名参数(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'; // what

如何让函数接受命名参数(
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);
}

首先,我真的建议坚持一种方法。如你所说,使用“命名”

或位置参数:

function foo(a = 'peanut', b = 'butter') {
    console.log(a, b);
}
选择一个更适合您的功能,不要将两者混用


如果出于某种原因,您确实需要这两种服务,您可以使用它们。只有当第一个位置参数不是对象时,它才能正常工作。我想提出以下一个成语:

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) {
    var opts = (arguments.length == 1 && typeof arguments[0] == "object")
      ? arguments[0]
      : {a, b};
    ({a = 'peanut', b = 'butter'} = opts);

    console.log(a, b);
}

您可以检测到两种场景之间的差异,但前提是您知道参数的预期类型,并且可以测试该类型以查看传递给函数的场景。@jfriend00考虑检查第一个参数是否为对象,以确定是否使用了命名参数,但如果我需要
a
也作为对象,该怎么办。这将混淆两种情况。有什么想法吗?检测不同变量传递方案的Javascript技术取决于参数的类型和数量。你必须设计一个方案,让你区分不同的可能性。你可以对可能性进行长时间的讨论。糖太多了。使用显式输入编写良好的函数。仅仅因为一种特定的语言可能会有某些东西,并不意味着你应该这样做。这是有道理的。但是,如果我使用
foo('hello')
,我将拥有
选项。长度===1
。然后,如果我要检查
options[0]
是否是一个对象,那么
foo({'whatever':'object'})
也会失败。还有其他想法吗?没错,你也可以检查第一个参数的类型,如果它是一个object
typeof
你是对的,但是如果我期望
a
是一个object呢?然后我会将一个对象传递给
a
,但随后它会被错误地识别为一个命名参数集。而且,
typeof options[0]==='object'
会打开一个蠕虫罐头:例如
typeof null==='object'
@AKG
typeof new String()=='object'
,考虑到您的参数要求,这更糟糕
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);
}