ES2015
В ES2015 параметр деструктурирования параметра может использоваться для имитации именованных параметров. Это потребует, чтобы вызывающий передал объект, но вы можете избежать всех проверок внутри функции, если вы также используете параметры по умолчанию:
myFunction({ param1 : 70, param2 : 175});
function myFunction({param1, param2}={}){
// ...
}
ES5
Там это способ приблизиться к тому, что вы хотите, но он основан на выходе Function.prototype.toString
[ES5] , который зависит от реализации в некоторой степени, поэтому он не может быть совместим с несколькими браузерами .
Идея состоит в том, чтобы проанализировать имена параметров из строкового представления функции, чтобы вы могли ассоциировать свойства объекта с соответствующим параметром.
Затем вызов функции мог выглядят как
func(a, b, {someArg: ..., someOtherArg: ...});
, где 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
, чтобы вы могли:
foo.execute(a, b, {posArg: ...});
Кажется, это проблема 1.6
Обновите до 2.1, и она исчезнет.