是否有一种方法可以动态地获取函数的函数参数名?
假设我的函数是这样的
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
}
现在,我如何从函数内部获得参数名称及其值的列表到数组中?
当前回答
我不知道如何得到参数列表但是你可以这样做来得到它期望的数量。注意,这只计算签名中没有默认值的参数:
函数foobar(a, b, c) {} 函数foobar2(a, b=false, c=false) {} console.log (foobar.length);//打印3个 console.log (foobar2.length);//打印1个
其他回答
我想建议解决方案,支持箭头函数像 我将本文用于基本正则表达式和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;
});
}
你可以使用"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]);
下面是来自AngularJS的代码,它在依赖注入机制中使用了这种技术。
以下是来自http://docs.angularjs.org/tutorial/step_05的解释
Angular的依赖注入器为你的控制器提供服务 当控制器被构造时。依赖注入器 负责创建服务可能的任何传递依赖项 拥有(服务通常依赖于其他服务)。 注意,参数的名称是重要的,因为注入器 使用这些来查找依赖项。
/**
* @ngdoc overview
* @name AUTO
* @description
*
* Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
*/
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn')
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
}
正确的方法是使用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()来实现。
下面我举个简单的例子:
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();