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

问题描述:

我怎么能有一个函数接受 命名参数( foo({a:'hello',b:'它是我'})位置参数( foo('你好','它是我'))?

How can I have a function accept either named arguments (foo({a: 'hello', b: 'it is me'})) or positional arguments (foo('hello', 'it is me'))?

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

I understand that named arguments can be simulated by passing an object to the function:

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);
}

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

But that does not allow me to accept positional arguments to be passed.

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

I would like to use ES6 but anything from ES5 would be ok too.

首先,我真的建议坚持使用一个appraoch。如你所说,使用 named

First of all, I really would recommend to stick with one appraoch. As you said, use either "named"

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

位置参数:

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

选择最适合您功能的产品,不要混合使用

Choose the one that fits your function better, do not mix both.

如果由于某种原因确实需要两者,标准重载技术可供您使用。只有当你的第一个位置参数不是一个对象时,它才能正常工作。我建议使用以下习语之一:

If you really need both for some reason, standard overloading techniques are available to you. It'll only work properly if your first positional argument is not an object. I would propose one of the following idioms:

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);
}

如果你需要默认值,它会变得丑陋:

and if you need default values, it gets ugly either way:

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);
}