是否有一种方法可以动态地获取函数的函数参数名?
假设我的函数是这样的
function doSomething(param1, param2, .... paramN){
// fill an array with the parameter name and value
// some other code
}
现在,我如何从函数内部获得参数名称及其值的列表到数组中?
是否有一种方法可以动态地获取函数的函数参数名?
假设我的函数是这样的
function doSomething(param1, param2, .... paramN){
// fill an array with the parameter name and value
// some other code
}
现在,我如何从函数内部获得参数名称及其值的列表到数组中?
当前回答
空格和注释不容易出错的解决方案是:
var fn = function(/* whoa) */ hi, you){};
fn.toString()
.replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg,'')
.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1]
.split(/,/)
["hi", "you"]
其他回答
从@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;
}
}
正确的方法是使用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()来实现。
无论哪种解决方案,它都不能破坏奇怪的函数,其toString()看起来也很奇怪:
function ( A, b
,c ,d
){}
另外,为什么要使用复杂的正则表达式?可以这样做:
function getArguments(f) {
return f.toString().split(')',1)[0].replace(/\s/g,'').substr(9).split(',');
}
这适用于每个函数,唯一的正则表达式是删除空白,由于.split技巧,它甚至不处理整个字符串。
这里有一种方法:
// 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的浏览器。
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;
}