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

假设我的函数是这样的

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

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


当前回答

函数参数字符串值图像动态从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>

其他回答

我想建议解决方案,支持箭头函数像 我将本文用于基本正则表达式和https://davidwalsh.name/javascript-arguments,并添加了箭头函数支持

(arg1,arg2) => {}

or

arg => {}



function getArgs(func) {
  if(func.length === 0){
      return []
  }

  let string = func.toString();

  let args;
  // First match everything inside the function argument parens. like `function (arg1,arg2) {}` or `async function(arg1,arg2) {}


  args = string.match(/(?:async|function)\s*.*?\(([^)]*)\)/)?.[1] ||
      // arrow functions with multiple arguments  like `(arg1,arg2) => {}`
         string.match(/^\s*\(([^)]*)\)\s*=>/)?.[1] ||
      // arrow functions with single argument without parens like `arg => {}`
         string.match(/^\s*([^=]*)=>/)?.[1]

  // Split the arguments string into an array comma delimited.
  return args.split(',').map(function(arg) {
    // Ensure no inline comments are parsed and trim the whitespace.
    return arg.replace(/\/\*.*\*\//, '').trim();
  }).filter(function(arg) {
    // Ensure no undefined values are added.
    return arg;
  });
}

我不知道这个解决方案是否适合您的问题,但它允许您重新定义任何您想要的函数,而无需更改使用它的代码。现有调用将使用定位参数,而函数实现可能使用“命名参数”(单个散列参数)。

我认为你无论如何都会修改现有的函数定义,所以,为什么不拥有一个工厂函数,让你想要的东西:

<!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>

希望能有所帮助。

下面的函数将返回传入的任何函数的参数名称的数组。

var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
  var fnStr = func.toString().replace(STRIP_COMMENTS, '');
  var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
  if(result === null)
     result = [];
  return result;
}

使用示例:

getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
getParamNames(function (a,/*b,c,*/d){}) // returns ['a','d']
getParamNames(function (){}) // returns []

编辑:

随着ES6的发明,这个函数可以被默认参数绊倒。这里有一个在大多数情况下都有效的快速技巧:

var STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;

我说大多数情况是因为有些事情会出错

function (a=4*(5/3), b) {} // returns ['a']

编辑: 我还注意到vikasde也想要数组中的参数值。这已经在名为arguments的局部变量中提供了。

节选自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments:

arguments对象不是数组。它类似于Array,但除了长度之外没有任何Array属性。例如,它没有pop方法。然而,它可以转换为一个真正的数组:

var args = Array.prototype.slice.call(arguments);

如果Array泛型可用,则可以使用以下方法:

var args = Array.slice(arguments);

从@jack-allan中得到答案,我稍微修改了函数,以允许ES6的默认属性,如:

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

仍然返回['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;
    }
}

无论哪种解决方案,它都不能破坏奇怪的函数,其toString()看起来也很奇怪:

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

另外,为什么要使用复杂的正则表达式?可以这样做:

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

这适用于每个函数,唯一的正则表达式是删除空白,由于.split技巧,它甚至不处理整个字符串。