This was such a pain to get working, and the solution isn’t ideal but it works.
I wanted to create an extensible library of functions which could be displayed in a UI. So I created functions like this:
function myFunction({a = '1', b = 2, c = [1,2], d = function(){return 'hi'}} = {}){};
To display the function options in a UI to allow users to call them, I wanted to get all the parameters and their defaults (and not pollute the global scope). I thought it’d be easy. It was not. This is my solution:
function getArguments(f) {
var t = {};
(new Function(`with(this) {
with(new Proxy(this,{
has(t, p) {return true;},
get(t, p) {return (p in t ? t : window)[p]}
})) {
${f.toString().match(/^function\s*[^(]*\(\s*{(.*)}\s*=\s*{}/ms)[1]}
}
}`)).call(t);
return Object.entries(t).map(v => ({name: v[0], value: v[1]}))
}
So you can call it like this:
getArguments(myFunction);
And it returns all the arguments and their default values:
Note: it only returns arguments which have defaults.