ES2015 und höher
In ES2015 kann die Parameterdestrukturierung verwendet werden, um benannte Parameter zu simulieren. Der Aufrufer müsste ein Objekt übergeben, aber Sie können alle Überprüfungen innerhalb der Funktion vermeiden, wenn Sie auch Standardparameter verwenden:
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
Es gibt eine Möglichkeit, dem, was Sie wollen, nahe zu kommen, aber sie basiert auf der Ausgabe von Function.prototype.toString
[ES5] , die in gewissem Maße von der Implementierung abhängt, sodass sie möglicherweise nicht browserübergreifend kompatibel ist.
Die Idee ist, die Parameternamen aus der Zeichenfolgendarstellung der Funktion zu analysieren, damit Sie die Eigenschaften eines Objekts dem entsprechenden Parameter zuordnen können.
Ein Funktionsaufruf könnte dann so aussehen
func(a, b, {someArg: ..., someOtherArg: ...});
wo a
und b
sind Positionsargumente und das letzte Argument ist ein Objekt mit benannten Argumenten.
Beispielsweise:
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);
};
};
}());
Welche würden Sie verwenden als:
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
Dieser Ansatz weist einige Nachteile auf (Sie wurden gewarnt!):
- Wenn das letzte Argument ein Objekt ist, wird es als "benannte Argumentobjekte" behandelt.
- Sie erhalten immer so viele Argumente, wie Sie in der Funktion definiert haben, aber einige von ihnen haben möglicherweise den Wert
undefined
(der sich davon unterscheidet, überhaupt keinen Wert zu haben). Das heißt, Sie können nicht arguments.length
testen, wie viele Argumente übergeben wurden.
Anstatt dass eine Funktion den Wrapper erstellt, können Sie auch eine Funktion verwenden, die eine Funktion und verschiedene Werte als Argumente akzeptiert, z
call(func, a, b, {posArg: ... });
oder sogar verlängern, Function.prototype
damit Sie tun können:
foo.execute(a, b, {posArg: ...});