Как получить имена / значения параметров функции динамически? - PullRequest
275 голосов
/ 17 июня 2009

Есть ли способ получить имена параметров функции динамически?

Допустим, моя функция выглядит следующим образом:

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

Теперь, как мне получить список имен параметров и их значений в массив из функции?

Ответы [ 31 ]

1 голос
/ 02 июля 2018

Правильный способ сделать это - использовать анализатор JS. Вот пример использования желудь .

const acorn = require('acorn');    

function f(a, b, c) {
   // ...
}

const argNames = acorn.parse(f).body[0].params.map(x => x.name);
console.log(argNames);  // Output: [ 'a', 'b', 'c' ]

Код здесь находит имена трех (формальных) параметров функции f. Это делается путем подачи f в acorn.parse().

1 голос
/ 21 ноября 2013
function getArgs(args) {
    var argsObj = {};

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

    while (tokens = /\s*([^,]+)/g.exec(argList)) {
        argsObj[tokens[1]] = args[argCnt++];
    }

    return argsObj;
}
0 голосов
/ 06 января 2018

Примечание: если вы хотите использовать деструктуризацию параметров ES6 в верхнем решении, добавьте следующую строку.

if (result[0] === '{' && result[result.length - 1 === '}']) result = result.slice(1, -1)
0 голосов
/ 19 мая 2017

Ниже приведу короткий пример:

function test(arg1,arg2){
    var funcStr = test.toString()
    var leftIndex = funcStr.indexOf('(');
    var rightIndex = funcStr.indexOf(')');
    var paramStr = funcStr.substr(leftIndex+1,rightIndex-leftIndex-1);
    var params = paramStr.split(',');
    for(param of params){
        console.log(param);   // arg1,arg2
    }
}

test();
0 голосов
/ 17 июня 2009

Вы можете получить доступ к значениям аргумента, переданным функции, используя свойство arguments.

    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]);    
0 голосов
/ 17 июня 2009

Вот один из способов:

// 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);

Примечание: это работает только в браузерах, которые поддерживают arguments.callee.

0 голосов
/ 03 августа 2016

Хорошо, так что старый вопрос с множеством адекватных ответов. Вот мое предложение, которое не использует регулярные выражения, за исключением простой задачи по удалению пробелов. (Я должен отметить, что функция "strips_comments" фактически удаляет их, а не удаляет их физически. Это потому, что я использую его в другом месте и по разным причинам нуждаюсь в расположении оригинальных токенов без комментариев)

Это довольно длинный блок кода, так как это вставка содержит мини-тестовую среду.

    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);
0 голосов
/ 29 июля 2015

Изображение строкового значения параметра функции динамически из JSON . Так как item.product_image2 является строкой URL, вам нужно поместить ее в кавычки, когда вы вызываете changeImage внутри параметра.

Моя функция Onclick

items+='<img src='+item.product_image1+' id="saleDetailDivGetImg">';
items+="<img src="+item.product_image2+"  onclick='changeImage(\""+item.product_image2+"\");'>";

Моя функция

<script type="text/javascript">
function changeImage(img)
 {
    document.getElementById("saleDetailDivGetImg").src=img;
    alert(img);
}
</script>
0 голосов
/ 02 февраля 2013

Это довольно легко.

На первом месте стоит устаревшая arguments.callee - ссылка на вызываемую функцию. Во-вторых, если у вас есть ссылка на вашу функцию, вы можете легко получить их текстовое представление. В-третьих, если вы вызываете свою функцию в качестве конструктора, вы также можете иметь ссылку через yourObject.constructor. NB: Первое решение устарело, поэтому, если вы не можете его не использовать, вы должны также подумать об архитектуре вашего приложения. Если вам не нужны точные имена переменных, просто используйте внутреннюю переменную функции arguments без всякой магии.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

Все они будут вызывать toString и заменять на re, чтобы мы могли создать помощника:

// getting names of declared parameters
var getFunctionParams = function (func) {
    return String(func).replace(/[^\(]+\(([^\)]*)\).*/m, '$1');
}

Некоторые примеры:

// Solution 1. deprecated! don't use it!
var myPrivateFunction = function SomeFuncName (foo, bar, buz) {
    console.log(getFunctionParams(arguments.callee));
};
myPrivateFunction (1, 2);

// Solution 2.
var myFunction = function someFunc (foo, bar, buz) {
    // some code
};
var params = getFunctionParams(myFunction);
console.log(params);

// Solution 3.
var cls = function SuperKewlClass (foo, bar, buz) {
    // some code
};
var inst = new cls();
var params = getFunctionParams(inst.constructor);
console.log(params);

Наслаждайтесь с JS!

UPD: Джеку Аллану было предоставлено немного лучшее решение. Джек Джек!

0 голосов
/ 15 января 2019

Попробуйте вручную:

function something(arg1, arg2) {
  console.log ( arg1 + arg2 );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...