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?

0voto

IanLancaster Punkte 181

Hinweis: Wenn Sie die ES6-Parameter-Destrukturierung mit der oberen Lösung verwenden möchten, fügen Sie die folgende Zeile hinzu.

if (result[0] === '{' && result[result.length - 1 === '}']) result = result.slice(1, -1)

0voto

letronje Punkte 8683

Über die Eigenschaft "arguments" können Sie auf die an eine Funktion übergebenen Argumente zugreifen.

    function doSomething()
    {
        var args = doSomething.arguments;
        var numArgs = args.length;
        for(var i = 0 ; i < numArgs ; i++)
        {
            console.log("arg " + (i+1) + " = " + args[i]);  
                    //console.log works with firefox + firebug
                    // you can use an alert to check in other browsers
        }
    }

    doSomething(1, '2', {A:2}, [1,2,3]);

0voto

Ates Goral Punkte 132294

Hier ist eine Möglichkeit:

// Utility function to extract arg name-value pairs
function getArgs(args) {
    var argsObj = {};

    var argList = /\(([^)]*)/.exec(args.callee)[1];
    var argCnt = 0;
    var tokens;
    var argRe = /\s*([^,]+)/g;

    while (tokens = argRe.exec(argList)) {
        argsObj[tokens[1]] = args[argCnt++];
    }

    return argsObj;
}

// Test subject
function add(number1, number2) {
    var args = getArgs(arguments);
    console.log(args); // ({ number1: 3, number2: 4 })
}

// Invoke test subject
add(3, 4);

Hinweis: Dies funktioniert nur bei Browsern, die die arguments.callee .

0voto

unsynchronized Punkte 4729

Also eine alte Frage mit vielen passenden Antworten. hier ist mein Angebot, das nicht Regex verwendet, außer für die lästige Aufgabe der Leerzeichen zu entfernen. (Ich sollte beachten, dass die "strips_comments" Funktion tatsächlich Räume sie aus, anstatt physisch zu entfernen. das ist, weil ich es an anderer Stelle verwenden und aus verschiedenen Gründen müssen die Standorte der ursprünglichen nicht-Kommentar-Token intakt bleiben)

Es ist ein ziemlich langer Codeblock, da dieses Einfügen ein Mini-Test-Framework enthält.

    function do_tests(func) {

    if (typeof func !== 'function') return true;
    switch (typeof func.tests) {
        case 'undefined' : return true;
        case 'object'    : 
            for (var k in func.tests) {

                var test = func.tests[k];
                if (typeof test==='function') {
                    var result = test(func);
                    if (result===false) {
                        console.log(test.name,'for',func.name,'failed');
                        return false;
                    }
                }

            }
            return true;
        case 'function'  : 
            return func.tests(func);
    }
    return true;
} 
function strip_comments(src) {

    var spaces=(s)=>{
        switch (s) {
            case 0 : return '';
            case 1 : return ' ';
            case 2 : return '  ';
        default : 
            return Array(s+1).join(' ');
        }
    };

    var c1 = src.indexOf ('/*'),
        c2 = src.indexOf ('//'),
        eol;

    var out = "";

    var killc2 = () => {
                out += src.substr(0,c2);
                eol =  src.indexOf('\n',c2);
                if (eol>=0) {
                    src = spaces(eol-c2)+'\n'+src.substr(eol+1);
                } else {
                    src = spaces(src.length-c2);
                    return true;
                }

             return false;
         };

    while ((c1>=0) || (c2>=0)) {
         if (c1>=0) {
             // c1 is a hit
             if ( (c1<c2) || (c2<0) )  {
                 // and it beats c2
                 out += src.substr(0,c1);
                 eol = src.indexOf('*/',c1+2);
                 if (eol>=0) {
                      src = spaces((eol-c1)+2)+src.substr(eol+2);
                 } else {
                      src = spaces(src.length-c1);
                      break;
                 }
             } else {

                 if (c2 >=0) {
                     // c2 is a hit and it beats c1
                     if (killc2()) break;
                 }
             }
         } else {
             if (c2>=0) {
                // c2 is a hit, c1 is a miss.
                if (killc2()) break;  
             } else {
                 // both c1 & c2 are a miss
                 break;
             }
         }

         c1 = src.indexOf ('/*');
         c2 = src.indexOf ('//');   
        }

    return out + src;
}

function function_args(fn) {
    var src = strip_comments(fn.toString());
    var names=src.split(')')[0].replace(/\s/g,'').split('(')[1].split(',');
    return names;
}

function_args.tests = [

     function test1 () {

            function/*al programmers will sometimes*/strip_comments_tester/* because some comments are annoying*/(
            /*see this---(((*/ src//)) it's an annoying comment does not help anyone understand if the 
            ,code,//really does
            /**/sucks ,much /*?*/)/*who would put "comment\" about a function like (this) { comment } here?*/{

            }

        var data = function_args(strip_comments_tester);

        return ( (data.length==4) &&
                 (data[0]=='src') &&
                 (data[1]=='code') &&
                 (data[2]=='sucks') &&
                 (data[3]=='much')  );

    }

];
do_tests(function_args);

0voto

Camilo Martin Punkte 35643

Wie auch immer die Lösung aussieht, sie darf nicht an seltsamen Funktionen scheitern, deren toString() sieht genauso seltsam aus:

function  (  A,  b
,c      ,d
){}

screenshot from console

Warum also komplexe reguläre Ausdrücke verwenden? Das kann man auch so machen:

function getArguments(f) {
    return f.toString().split(')',1)[0].replace(/\s/g,'').substr(9).split(',');
}

Dies funktioniert überall mit jeder Funktion, und die einzige Regex ist die Entfernung von Leerzeichen, die nicht einmal die gesamte Zeichenkette verarbeitet, da die .split Trick.

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