Rob*_*ben 176 javascript function optional-parameters named-parameters
我发现C#中的命名参数功能在某些情况下非常有用.
calculateBMI(70, height: 175);
Run Code Online (Sandbox Code Playgroud)
如果我想在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
}
Run Code Online (Sandbox Code Playgroud)
我已经使用过这种方法.还有另外一种方法吗?
我可以使用任何库来做这件事.(或者有人可以指出我已经做过的那个)
Fel*_*ing 168
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...
}
Run Code Online (Sandbox Code Playgroud)
ES5
有一种方法可以接近你想要的,但它基于Function.prototype.toString
[ES5]的输出,这在某种程度上取决于实现,因此它可能不是跨浏览器兼容的.
我们的想法是从函数的字符串表示中解析参数名称,以便您可以将对象的属性与相应的参数相关联.
然后函数调用可能看起来像
func(a, b, {someArg: ..., someOtherArg: ...});
Run Code Online (Sandbox Code Playgroud)
where 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);
};
};
}());
Run Code Online (Sandbox Code Playgroud)
您将使用哪个:
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
Run Code Online (Sandbox Code Playgroud)
这种方法有一些缺点(你已被警告过!):
undefined
(这与完全没有值的情况不同).这意味着您不能用于arguments.length
测试已传递的参数数量.您可以使用一个函数来接受函数和各种值作为参数,而不是创建包装器的函数
call(func, a, b, {posArg: ... });
Run Code Online (Sandbox Code Playgroud)
甚至延伸,Function.prototype
以便您可以:
foo.execute(a, b, {posArg: ...});
Run Code Online (Sandbox Code Playgroud)
Utk*_*nos 62
不 - 对象方法是JavaScript的答案.如果你的函数需要一个对象而不是单独的params,那么这没有问题.
Ray*_*rea 29
这个问题一直是我的一个宠儿.我是一位经验丰富的程序员,拥有多种语言.我有幸使用的一种我最喜欢的语言是Python.Python支持命名参数,没有任何诡计....自从我开始使用Python(前一段时间)后,一切都变得更加容易.我相信每种语言都应该支持命名参数,但事实并非如此.
很多人说只是使用"传递对象"技巧,以便你有命名参数.
/**
* My Function
*
* @param {Object} arg1 Named arguments
*/
function myFunc(arg1) { }
myFunc({ param1 : 70, param2 : 175});
Run Code Online (Sandbox Code Playgroud)
这很有效,除了......当涉及到大多数IDE时,我们很多开发人员依赖IDE中的类型/参数提示.我个人使用PHP Storm(以及其他JetBrains IDE,如PyCharm for python和AppCode for Objective C)
使用"传递对象"技巧的最大问题是,当您调用该函数时,IDE会为您提供单一类型提示,就是这样......我们应该知道哪些参数和类型应该进入arg1对象?
所以..."传递一个对象"技巧对我来说不起作用......在我知道函数所期望的参数之前,它实际上会导致更多的麻烦,不得不查看每个函数的docblock ....当然,这对于当您维护现有代码时,但编写新代码非常糟糕.
好吧,这是我使用的技术....现在,它可能存在一些问题,而且一些开发人员可能会告诉我,我做错了,而且我对这些事情持开放态度......我总是愿意考虑更好的方法来完成任务......所以,如果这个技术存在问题,那么欢迎提出意见.
/**
* My Function
*
* @param {string} arg1 Argument 1
* @param {string} arg2 Argument 2
*/
function myFunc(arg1, arg2) { }
var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');
Run Code Online (Sandbox Code Playgroud)
这样,我充分利用了两个世界......新代码很容易编写,因为我的IDE给了我所有正确的参数提示......而且,在稍后维护代码的同时,我可以一目了然地看到,不仅仅是传递给函数的值,也是参数的名称.我看到的唯一开销是将您的参数名称声明为局部变量,以防止污染全局命名空间.当然,这是一个额外的打字,但与编写新代码或维护现有代码时查找docblock所花费的时间相比微不足道.
dav*_*v_i 20
如果你想清楚说明每个参数是什么,而不仅仅是调用
someFunction(70, 115);
Run Code Online (Sandbox Code Playgroud)
为什么不做以下
var width = 70, height = 115;
someFunction(width, height);
Run Code Online (Sandbox Code Playgroud)
当然,这是一个额外的代码行,但它在可读性上获胜.
另一种方法是使用合适对象的属性,例如:
function plus(a,b) { return a+b; };
Plus = { a: function(x) { return { b: function(y) { return plus(x,y) }}},
b: function(y) { return { a: function(x) { return plus(x,y) }}}};
sum = Plus.a(3).b(5);
Run Code Online (Sandbox Code Playgroud)
当然,对于这个组成的例子,它有点毫无意义.但是在函数看起来像的情况下
do_something(some_connection_handle, some_context_parameter, some_value)
Run Code Online (Sandbox Code Playgroud)
它可能更有用.它还可以与"parameterfy"思想相结合,以通用方式从现有函数中创建这样的对象.这是为每个参数创建一个可以评估函数的部分评估版本的成员.
这个想法当然与Schönfinkeling又名Currying有关.