有没有办法在JavaScript的函数调用中提供命名参数? [英] Is there a way to provide named parameters in a function call in JavaScript?

查看:108
本文介绍了有没有办法在JavaScript的函数调用中提供命名参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I find the named parameters feature in C# quite useful in some cases.

calculateBMI(70, height: 175);

如果我想在JavaScript中使用该怎么办?

What can I use if I want this in 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
}

我已经使用过这种方法.还有另一种方法吗?

That approach I’ve already used. Is there another way?

我可以使用任何库来做到这一点.

I’m okay using any library to do this.

推荐答案

ES2015及更高版本

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

In ES2015, parameter destructuring can be used to simulate named parameters. It would require the caller to pass an object, but you can avoid all of the checks inside the function if you also use default parameters:

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] ,在某种程度上取决于实现,因此它可能与跨浏览器不兼容.

There is a way to come close to what you want, but it is based on the output of Function.prototype.toString [ES5], which is implementation dependent to some degree, so it might not be cross-browser compatible.

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

The idea is to parse the parameter names from the string representation of the function so that you can associate the properties of an object with the corresponding parameter.

函数调用可能看起来像

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

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

where a and b are positional arguments and the last argument is an object with named arguments.

例如:

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 

演示

此方法有一些缺点(已警告您!):

There are some drawbacks to this approach (you have been warned!):

  • 如果最后一个参数是一个对象,则将其视为命名参数对象"
  • 您将始终获得与在函数中定义的参数一样多的参数,但是其中一些参数可能具有值undefined(这与根本没有值不同).这意味着您不能使用arguments.length来测试已传递了多少个参数.
  • If the last argument is an object, it is treated as a "named argument objects"
  • You will always get as many arguments as you defined in the function, but some of them might have the value undefined (that's different from having no value at all). That means you cannot use arguments.length to test how many arguments have been passed.

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

Instead of having a function creating the wrapper, you could also have a function which accepts a function and various values as arguments, such as

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

甚至扩展Function.prototype以便您可以做到:

or even extend Function.prototype so that you could do:

foo.execute(a, b, {posArg: ...});

这篇关于有没有办法在JavaScript的函数调用中提供命名参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆