351 Stimmen

Wie kann man die Namen/Werte von Funktionsparametern dynamisch ermitteln?

Gibt es eine Möglichkeit, die Namen der Funktionsparameter einer Funktion dynamisch abzurufen?

Nehmen wir an, meine Funktion sieht wie folgt aus:

function doSomething(param1, param2, .... paramN){
   // fill an array with the parameter name and value
   // some other code 
}

Nun, wie würde ich eine Liste der Parameternamen und ihre Werte in ein Array von innerhalb der Funktion erhalten?

9voto

Will Punkte 2334
(function(a,b,c){}).toString().replace(/.*\(|\).*/ig,"").split(',')

\=> [ "a", "b", "c" ]

8voto

hugoware Punkte 34313

Ich habe das schon öfter versucht, aber nie eine praktische Lösung gefunden. Ich endete in ein Objekt statt übergeben und dann in einer Schleife durch sie.

//define like
function test(args) {
    for(var item in args) {
        alert(item);
        alert(args[item]);
    }
}

//then used like
test({
    name:"Joe",
    age:40,
    admin:bool
});

5voto

Ionuț G. Stan Punkte 168218

Ich weiß nicht, ob diese Lösung für Ihr Problem geeignet ist, aber Sie können damit jede beliebige Funktion umdefinieren, ohne den Code, der sie verwendet, ändern zu müssen. Bestehende Aufrufe verwenden positionierte Parameter, während die Funktionsimplementierung "benannte Parameter" (ein einzelner Hash-Parameter) verwenden kann.

Ich dachte, dass Sie sowieso bestehende Funktionsdefinitionen ändern werden, warum also nicht eine Fabrikfunktion haben, die genau das macht, was Sie wollen:

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var withNamedParams = function(params, lambda) {
    return function() {
        var named = {};
        var max   = arguments.length;

        for (var i=0; i<max; i++) {
            named[params[i]] = arguments[i];
        }

        return lambda(named);
    };
};

var foo = withNamedParams(["a", "b", "c"], function(params) {
    for (var param in params) {
        alert(param + ": " + params[param]);
    }
});

foo(1, 2, 3);
</script>
</head>
<body>

</body>
</html>

Ich hoffe, es hilft.

4voto

SanBen Punkte 1709

Da dies noch nicht erwähnt wurde, können Sie, wenn Sie Typescript verwenden, bei der Verwendung von Dekoratoren Metadaten ausgeben, die es Ihnen ermöglichen, die Parametertypen zu erhalten.

Metadaten werden nur ausgegeben, wenn die Klasse/Funktion/Prop einen Dekorator hat.
Es spielt keine Rolle, welcher Dekorateur.

Diese Funktion kann aktiviert werden durch die Einstellung emitDecoratorMetadata in tsconfig.json auf true setzen

{
  "compilerOptions": {
    "emitDecoratorMetadata": true
  }
}

Da sich die Metadaten noch in einem frühen Vorschlag die reflect-Metadaten muss installiert sein, sonst wird Reflect.getMetadata nicht definiert.

npm install reflect-metadata

Sie können es wie folgt verwenden:

const AnyDecorator = () : MethodDecorator => {
    return target => { }
}

class Person{
    @AnyDecorator()
    sayHello(other: Person){}
}
const instance = new Person();
// This returns: Function
const funcType = Reflect.getMetadata('design:type', instance.sayHello);
// Returns an array of types, here it would be: [Person]
const funcParams = Reflect.getMetadata('design:paramtypes', instance.sayHello);

In neueren Versionen von Angular wird dies zum Beispiel verwendet, um zu bestimmen, was injiziert werden soll -> https://stackoverflow.com/a/53041387/1087372

4voto

thelastshadow Punkte 3205

Die Einnahme der Antwort von @jack-allan Ich habe die Funktion leicht modifiziert, um ES6-Standardeigenschaften wie zu ermöglichen:

function( a, b = 1, c ){};

noch zurückzukehren [ 'a', 'b' ]

/**
 * Get the keys of the paramaters of a function.
 *
 * @param {function} method  Function to get parameter keys for
 * @return {array}
 */
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /(?:^|,)\s*([^\s,=]+)/g;
function getFunctionParameters ( func ) {
    var fnStr = func.toString().replace(STRIP_COMMENTS, '');
    var argsList = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')'));
    var result = argsList.match( ARGUMENT_NAMES );

    if(result === null) {
        return [];
    }
    else {
        var stripped = [];
        for ( var i = 0; i < result.length; i++  ) {
            stripped.push( result[i].replace(/[\s,]/g, '') );
        }
        return stripped;
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X