有没有办法在JavaScript中检索函数的默认参数值?
Build > Clean Project
有没有办法在这里获得function foo(x = 5) {
// things I do not control
}
的默认值?最理想的是:
x
请注意,getDefaultValues(foo); // {"x": 5}
该函数不起作用,因为它会在非常量的默认值上中断。
答案 0 :(得分:4)
由于我们在JS中没有经典的反射,正如你可以在C#,Ruby等上找到的那样,我们必须依靠我喜欢的工具之一,正则表达式来为我们完成这项工作:
let b = "foo";
function fn (x = 10, /* woah */ y = 20, z, a = b) { /* ... */ }
fn.toString()
.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1] // Get the parameters declaration between the parenthesis
.replace(/(\/\*[\s\S]*?\*\/)/mg,'') // Get rid of comments
.split(',')
.reduce(function (parameters, param) { // Convert it into an object
param = param.match(/([_$a-zA-Z][^=]*)(?:=([^=]+))?/); // Split parameter name from value
parameters[param[1].trim()] = eval(param[2]); // Eval each default value, to get strings, variable refs, etc.
return parameters;
}, {});
// Object { x: 10, y: 20, z: undefined, a: "foo" }
如果您打算使用此功能,请确保您正在缓存正则表达式以提高性能。
感谢bubersson关于前两个正则表达式的提示
答案 1 :(得分:1)
我通过从函数的字符串版本中提取参数来解决它:
NiceToMeetYou
参数提取方法取自这里:Regular Expression to get parameter list from function definition
喝彩!
PS。正如你所看到的,它将整数转换为字符串,有时可能很烦人。只是确保事先知道输入类型或确保它不重要。
答案 2 :(得分:1)
正如问题所述,使用toString
是一种有限的解决方案。它将产生一个结果,可以是从值文字到方法调用的任何内容。然而,语言本身就是这种情况 - 它允许这样的声明。将任何不是文字值的内容转换为值都是最好的启发式猜测。考虑以下2个代码片段:
let def;
function withDef(v = def) {
console.log(v);
}
getDefaultValues(withDef); // undefined, or unknown?
def = prompt('Default value');
withDef();
function wrap() {
return (new Function(prompt('Function body')))();
// mutate some other value(s) --> side effects
}
function withDef(v = wrap()) {
console.log(v);
}
withDef();
getDefaultValues(withDef); // unknown?
虽然可以评估第一个示例(必要时递归)以提取undefined
以及稍后提取任何其他值,但第二个示例是真正未定义的,因为默认值是非确定的。当然,您可以将prompt()
替换为任何其他外部输入/随机生成器。
所以最好的答案是你已经拥有的那个。使用toString
,如果需要,可以使用eval()
提取的内容 - 但会产生副作用。
答案 3 :(得分:0)
有没有办法在这里获取
x
的默认值?
不,没有内置的反射功能可以做这些事情,而且无论如何都是完全不可能的,因为在JavaScript中设计了默认参数。
请注意
toString()
该函数不起作用,因为它会在非常量的默认值上中断。
事实上。找到答案的唯一方法是调用函数,因为默认值可能取决于调用。想想
function(x, y=x) { … }
并尝试获得y
默认值的合理表示。
在其他语言中,您可以访问默认值,因为它们是常量(在定义期间进行评估),或者它们的反射允许您分解表达式并在定义它们的上下文中对它们进行评估。
相比之下,JS会在每次调用函数时评估参数初始化表达式(如果需要) - 详细了解How does this
work in default parameters?。这些表达式就好像它们是函数体的一部分一样,不能以编程方式访问,就像它们引用的任何值隐藏在函数的私有闭包范围内一样。
如果你有一个允许访问闭包值的反射API(比如引擎的调试API),那么你也可以访问默认值。
根据公共财产或行为来区分function(x, y=x) {…}
和function(x) { var y=x; …}
是不可能的,唯一的方法是.toString()
。你通常不想依赖它。