我发现 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 }
我已经使用了这种方法。还有其他方法吗?
我可以使用任何库来执行此操作。
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] 的输出,这在某种程度上依赖于实现,因此它可能不兼容跨浏览器。
Function.prototype.toString
这个想法是从函数的字符串表示中解析参数名称,以便您可以将对象的属性与相应的参数相关联。
函数调用可能看起来像
func(a, b, {someArg: ..., someOtherArg: ...});
其中a和b是位置参数,最后一个参数是具有命名参数的对象。
a
b
例如:
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,以便您可以执行以下操作:
Function.prototype
foo.execute(a, b, {posArg: ...});