小编典典

有没有办法在 JavaScript 的函数调用中提供命名参数?

all

我发现 C# 中的命名参数功能在某些情况下非常有用。

calculateBMI(70, height: 175);

如果我想在 JavaScript 中使用它,我可以使用什么?


我不想要的是这样的:

myFunction({ param1: 70, param2: 175 });

function myFunction(params){
  // Check if params is an object
  // Check if the parameters I need are non-null
  // Blah blah
}

我已经使用了这种方法。还有其他方法吗?

我可以使用任何库来执行此操作。


阅读 92

收藏
2022-04-07

共1个答案

小编典典

ES2015 及更高版本

在 ES2015 中,可以使用 参数解构来模拟命名参数。 它需要调用者传递一个对象,但如果您还使用默认参数,则可以避免函数内部的所有检查:

myFunction({ param1 : 70, param2 : 175});

function myFunction({param1, param2}={}){
  // ...function body...
}

// Or with defaults, 
function myFunc({
  name = 'Default user',
  age = 'N/A'
}={}) {
  // ...function body...
}

ES5

有一种方法可以接近您想要的,但它基于Function.prototype.toString
[ES5]
的输出,这在某种程度上依赖于实现,因此它可能不兼容跨浏览器。

这个想法是从函数的字符串表示中解析参数名称,以便您可以将对象的属性与相应的参数相关联。

函数调用可能看起来像

func(a, b, {someArg: ..., someOtherArg: ...});

其中ab是位置参数,最后一个参数是具有命名参数的对象。

例如:

var parameterfy = (function() {
    var pattern = /function[^(]*\(([^)]*)\)/;

    return function(func) {
        // fails horribly for parameterless functions ;)
        var args = func.toString().match(pattern)[1].split(/,\s*/);

        return function() {
            var named_params = arguments[arguments.length - 1];
            if (typeof named_params === 'object') {
                var params = [].slice.call(arguments, 0, -1);
                if (params.length < args.length) {
                    for (var i = params.length, l = args.length; i < l; i++) {
                        params.push(named_params[args[i]]);
                    }
                    return func.apply(this, params);
                }
            }
            return func.apply(null, arguments);
        };
    };
}());

您将用作:

var foo = parameterfy(function(a, b, c) {
    console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);     
});

foo(1, 2, 3); // a is 1  | b is 2  | c is 3
foo(1, {b:2, c:3}); // a is 1  | b is 2  | c is 3
foo(1, {c:3}); // a is 1  | b is undefined  | c is 3
foo({a: 1, c:3}); // a is 1  | b is undefined  | c is 3

演示

这种方法有一些 缺点 (您已被警告!):

  • 如果最后一个参数是对象,则将其视为“命名参数对象”
  • 您将始终获得与函数中定义的参数一样多的参数,但其中一些可能具有值undefined(这与根本没有值不同)。这意味着你不能用它arguments.length来测试已经传递了多少参数。

除了让函数创建包装器之外,您还可以拥有一个接受函数和各种值作为参数的函数,例如

call(func, a, b, {posArg: ... });

甚至扩展Function.prototype,以便您可以执行以下操作:

foo.execute(a, b, {posArg: ...});
2022-04-07