是否有一种方法可以动态地获取函数的函数参数名?
假设我的函数是这样的
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
}
现在,我如何从函数内部获得参数名称及其值的列表到数组中?
当前回答
这很简单。
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杰克!
其他回答
我通常是怎么做的:
function name(arg1, arg2){
var args = arguments; // array: [arg1, arg2]
var objecArgOne = args[0].one;
}
name({one: "1", two: "2"}, "string");
你甚至可以通过函数名引用参数,比如:
name.arguments;
希望这能有所帮助!
我知道这是一个老问题,但初学者一直在复制从函数的字符串表示中提取参数名的解决方案,就好像这是任何代码中的良好实践一样。大多数情况下,这只是隐藏了逻辑中的缺陷。
在函数声明的圆括号中写入参数名可以看作是创建变量的一种简写语法。这样的:
function doSomething(foo, bar) {
console.log("does something");
}
...类似于这个:
function doSomething() {
var foo = arguments[0];
var bar = arguments[1];
console.log("does something");
}
变量本身存储在函数的作用域中,而不是作为对象中的属性。就像您不能用代码操作变量的名称一样,也无法检索参数的名称,因为它不是字符串,并且可以在JIT编译期间消除它。
我一直认为函数的字符串表示形式是调试目的的工具,特别是因为这个参数类数组对象。首先,您不需要为参数指定名称。如果您尝试解析一个字符串化函数,它实际上不会告诉您它可能接受的额外未命名参数。
还有一种更糟糕、更常见的情况。如果一个函数有超过3或4个参数,那么向它传递一个更容易处理的对象可能是合乎逻辑的。
function saySomething(obj) {
if(obj.message) console.log((obj.sender || "Anon") + ": " + obj.message);
}
saySomething({sender: "user123", message: "Hello world"});
在这种情况下,函数本身将能够读取它接收到的对象,并查找其属性并获得它们的名称和值,但试图解析函数的字符串表示只能为参数提供“obj”,这一点用都没有。
这个问题的答案需要3个步骤:
To get the values of the actual parameters passed to the function (let's call it argValues). This is straight forward as it will be available as arguments inside the function. To get the parameter names from the function signature (let's call it argNames). This not as easy and requires parsing the function. Instead of doing the complex regex yourself and worrying about edge cases (default parameters, comments, ...), you can use a library like babylon that will parse the function into an abstract syntax tree from which you can obtain the names of parameters. The last step is to join the 2 arrays together into 1 array that has the name and value of all the parameters.
代码是这样的
const babylon = require("babylon")
function doSomething(a, b, c) {
// get the values of passed argumenst
const argValues = arguments
// get the names of the arguments by parsing the function
const ast = babylon.parse(doSomething.toString())
const argNames = ast.program.body[0].params.map(node => node.name)
// join the 2 arrays, by looping over the longest of 2 arrays
const maxLen = Math.max(argNames.length, argValues.length)
const args = []
for (i = 0; i < maxLen; i++) {
args.push({name: argNames[i], value: argValues[i]})
}
console.log(args)
// implement the actual function here
}
doSomething(1, 2, 3, 4)
日志对象将为
[
{
"name": "a",
"value": 1
},
{
"name": "c",
"value": 3
},
{
"value": 4
}
]
下面是一个工作示例https://tonicdev.com/5763eb77a945f41300f62a79/5763eb77a945f41300f62a7a
注意:如果你想使用ES6参数解构与顶部解决方案添加下面的行。
if (result[0] === '{' && result[result.length - 1 === '}']) result = result.slice(1, -1)
下面我举个简单的例子:
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();