在javascript中命名参数 [英] Named parameters in javascript

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

问题描述

  calculateBMI(70,height:175);我发现C#中的命名参数功能在某些情况下非常有用。 

如果我想在 javascript 中使用它,该怎么办?






我不想要的是 -

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

函数myFunction(params){
//检查参数是否为对象
//检查我需要的参数是否为非空
// blah- blah
}

我已经使用过这种方法。有没有另外一种方法?



我可以使用任何库来做到这一点。 (或者有人可以指点我已经做过的) / p>

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

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

函数myFunction({param1,param2} = {}){
// ...
}






ES5



一种接近你想要的方式,但它是基于 Function.prototype.toString [ES5] ,它在某种程度上依赖于实现,所以它可能不会交叉-browser compatible。



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

函数调用可能看起来像

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

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



例如:

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

返回函数(func){
//对于无参数函数可怕的失败;
var args = func.toString()。match(pattern)[1]。分裂(/,\s * /);

return function(){
var named_pa​​rams = arguments [arguments.length - 1];
if(typeof named_pa​​rams ==='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_pa​​rams [参数[I]]);
}
返回func.apply(this,params);
}
}
返回func.apply(null,arguments);
};
};
}());

您可以用作:

 var foo = parameterfy(函数(a,b,c){
console.log('a是'+ a,'| b是'+ b,'| c是'+ c);
});

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

DEMO



这种方法存在一些缺点 !):


  • 如果最后一个参数是一个对象,它将被视为一个命名参数对象

  • 您将始终获得您在函数中定义的多个参数,但其中一些参数的值可能(这不同于完全没有值) 。这意味着您不能使用 arguments.length 来测试已传递了多少个参数。




你可以有一个函数接受一个函数和各种值作为参数,而不是创建一个包装函数,比如

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

甚至可以扩展 Function.prototype 你可以这样做:

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


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

calculateBMI(70, height: 175);

What if I want this in javascript?


What I don't want is -

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 do this. (Or somebody can point me to one that already does)

解决方案

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}={}){
  // ...
}


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.

A function call could then look like

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

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

For example:

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

Which you would use as:

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 

DEMO

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

  • 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: ... });

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

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

这篇关于在javascript中命名参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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