是否有一种方法可以动态地获取函数的函数参数名?

假设我的函数是这样的

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

现在,我如何从函数内部获得参数名称及其值的列表到数组中?


当前回答

这是我的解决方案——它适用于命名函数和未命名函数,异步和非异步函数,异步和非异步lambdas,以及带和不带paren的lambdas。

const STRIP_COMMENTS = /((\/\/.*$)|(\/\*.*\*\/))/mg;
const STRIP_KEYWORDS = /(\s*async\s*|\s*function\s*)+/;
const ARGUMENT_NAMES = /\(([^)]+)\)\s*=>|([a-zA-Z_$]+)\s*=>|[a-zA-Z_$]+\(([^)]+)\)|\(([^)]+)\)/;
const ARGUMENT_SPLIT = /[ ,\n\r\t]+/;
function getParamNames(func) {
    const fnStr = func.toString()
        .replace(STRIP_COMMENTS, "")
        .replace(STRIP_KEYWORDS, "")
        .trim();
    const matches = ARGUMENT_NAMES.exec(fnStr);
    var match;
    if (matches) {
        for (var i = 1; i < matches.length; i++) {
            if (matches[i]) {
                match = matches[i];
                break;
            } 
        }
    }
    if (match === undefined) {
        return [];
    }
    return match.split(ARGUMENT_SPLIT).filter(part => part !== "");
}

其他回答

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

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

我不知道如何得到参数列表但是你可以这样做来得到它期望的数量。注意,这只计算签名中没有默认值的参数:

函数foobar(a, b, c) {} 函数foobar2(a, b=false, c=false) {} console.log (foobar.length);//打印3个 console.log (foobar2.length);//打印1个

//See this:


// global var, naming bB
var bB = 5;

//  Dependency Injection cokntroller
var a = function(str, fn) {
  //stringify function body
  var fnStr = fn.toString();

  // Key: get form args to string
  var args = fnStr.match(/function\s*\((.*?)\)/);
  // 
  console.log(args);
  // if the form arg is 'bB', then exec it, otherwise, do nothing
  for (var i = 0; i < args.length; i++) {
    if(args[i] == 'bB') {
      fn(bB);
    }
  }
}
// will do nothing
a('sdfdfdfs,', function(some){
alert(some)
});
// will alert 5

a('sdfdsdsfdfsdfdsf,', function(bB){
alert(bB)
});

// see, this shows you how to get function args in string

下面是一个更新的解决方案,试图以一种紧凑的方式解决上述所有边缘情况:

function $args(func) {  
    return (func + '')
      .replace(/[/][/].*$/mg,'') // strip single-line comments
      .replace(/\s+/g, '') // strip white space
      .replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments  
      .split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters  
      .replace(/=[^,]+/g, '') // strip any ES6 defaults  
      .split(',').filter(Boolean); // split & filter [""]
}  

简化的测试输出(完整的测试用例附在下面):

'function (a,b,c)...' // returns ["a","b","c"]
'function ()...' // returns []
'function named(a, b, c) ...' // returns ["a","b","c"]
'function (a /* = 1 */, b /* = true */) ...' // returns ["a","b"]
'function fprintf(handle, fmt /*, ...*/) ...' // returns ["handle","fmt"]
'function( a, b = 1, c )...' // returns ["a","b","c"]
'function (a=4*(5/3), b) ...' // returns ["a","b"]
'function (a, // single-line comment xjunk) ...' // returns ["a","b"]
'function (a /* fooled you...' // returns ["a","b"]
'function (a /* function() yes */, \n /* no, */b)/* omg! */...' // returns ["a","b"]
'function ( A, b \n,c ,d \n ) \n ...' // returns ["A","b","c","d"]
'function (a,b)...' // returns ["a","b"]
'function $args(func) ...' // returns ["func"]
'null...' // returns ["null"]
'function Object() ...' // returns []

function $args(func) { return (func + '') .replace(/[/][/].*$/mg,'') // strip single-line comments .replace(/\s+/g, '') // strip white space .replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments .split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters .replace(/=[^,]+/g, '') // strip any ES6 defaults .split(',').filter(Boolean); // split & filter [""] } // test cases document.getElementById('console_info').innerHTML = ( [ // formatting -- typical function(a,b,c){}, function(){}, function named(a, b, c) { /* multiline body */ }, // default values -- conventional function(a /* = 1 */, b /* = true */) { a = a||1; b=b||true; }, function fprintf(handle, fmt /*, ...*/) { }, // default values -- ES6 "function( a, b = 1, c ){}", "function (a=4*(5/3), b) {}", // embedded comments -- sardonic function(a, // single-line comment xjunk) {} b //,c,d ) // single-line comment {}, function(a /* fooled you{*/,b){}, function /* are you kidding me? (){} */(a /* function() yes */, /* no, */b)/* omg! */{/*}}*/}, // formatting -- sardonic function ( A, b ,c ,d ) { }, // by reference this.jQuery || function (a,b){return new e.fn.init(a,b,h)}, $args, // inadvertent non-function values null, Object ].map(function(f) { var abbr = (f + '').replace(/\n/g, '\\n').replace(/\s+|[{]+$/g, ' ').split("{", 1)[0] + "..."; return " '" + abbr + "' // returns " + JSON.stringify($args(f)); }).join("\n") + "\n"); // output for copy and paste as a markdown snippet <pre id='console_info'></pre>

函数参数字符串值图像动态从JSON。因为项目。product_image2是一个URL字符串,当你在参数内部调用changeImage时,你需要把它放在引号中。

我的功能

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>