是否有一种方法可以动态地获取函数的函数参数名?
假设我的函数是这样的
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
}
现在,我如何从函数内部获得参数名称及其值的列表到数组中?
当前回答
无论哪种解决方案,它都不能破坏奇怪的函数,其toString()看起来也很奇怪:
function ( A, b
,c ,d
){}
另外,为什么要使用复杂的正则表达式?可以这样做:
function getArguments(f) {
return f.toString().split(')',1)[0].replace(/\s/g,'').substr(9).split(',');
}
这适用于每个函数,唯一的正则表达式是删除空白,由于.split技巧,它甚至不处理整个字符串。
其他回答
下面是来自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;
}
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;
}
我通常是怎么做的:
function name(arg1, arg2){
var args = arguments; // array: [arg1, arg2]
var objecArgOne = args[0].one;
}
name({one: "1", two: "2"}, "string");
你甚至可以通过函数名引用参数,比如:
name.arguments;
希望这能有所帮助!
//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
这很简单。
At the first there is a deprecated arguments.callee — a reference to called function. At the second if you have a reference to your function you can easily get their textual representation. At the third if you calling your function as constructor you can also have a link via yourObject.constructor. NB: The first solution deprecated so if you can't to not use it you must also think about your app architecture. If you don't need exact variable names just use inside a function internal variable arguments without any magic.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee
它们都将调用toString并将其替换为re,这样我们就可以创建一个helper:
// 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:实际上杰克·艾伦提供了一个更好的解决方案。GJ杰克!