How to get function parameter names/values dynamically?
Solution 1
The following function will return an array of the parameter names of any function passed in.
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
var fnStr = func.toString().replace(STRIP_COMMENTS, '');
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
if(result === null)
result = [];
return result;
}
Example usage:
getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
getParamNames(function (a,/*b,c,*/d){}) // returns ['a','d']
getParamNames(function (){}) // returns []
Edit:
With the invent of ES6 this function can be tripped up by default parameters. Here is a quick hack which should work in most cases:
var STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;
I say most cases because there are some things that will trip it up
function (a=4*(5/3), b) {} // returns ['a']
Edit: I also note vikasde wants the parameter values in an array also. This is already provided in a local variable named arguments.
excerpt from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments:
The arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length. For example, it does not have the pop method. However it can be converted to a real Array:
var args = Array.prototype.slice.call(arguments);
If Array generics are available, one can use the following instead:
var args = Array.slice(arguments);
Solution 2
Below is the code taken from AngularJS which uses the technique for its dependency injection mechanism.
And here is an explanation of it taken from http://docs.angularjs.org/tutorial/step_05
Angular's dependency injector provides services to your controller when the controller is being constructed. The dependency injector also takes care of creating any transitive dependencies the service may have (services often depend upon other services).
Note that the names of arguments are significant, because the injector uses these to look up the dependencies.
/**
* @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;
}
Solution 3
Here is an updated solution that attempts to address all the edge cases mentioned above in a compact way:
function $args(func) {
return (func + '')
.replace(/[/][/].*$/mg,'') // strip single-line comments
.replace(/\s+/g, '') // strip white space
.replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments
.split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters
.replace(/=[^,]+/g, '') // strip any ES6 defaults
.split(',').filter(Boolean); // split & filter [""]
}
Abbreviated test output (full test cases are attached below):
'function (a,b,c)...' // returns ["a","b","c"]
'function ()...' // returns []
'function named(a, b, c) ...' // returns ["a","b","c"]
'function (a /* = 1 */, b /* = true */) ...' // returns ["a","b"]
'function fprintf(handle, fmt /*, ...*/) ...' // returns ["handle","fmt"]
'function( a, b = 1, c )...' // returns ["a","b","c"]
'function (a=4*(5/3), b) ...' // returns ["a","b"]
'function (a, // single-line comment xjunk) ...' // returns ["a","b"]
'function (a /* fooled you...' // returns ["a","b"]
'function (a /* function() yes */, \n /* no, */b)/* omg! */...' // returns ["a","b"]
'function ( A, b \n,c ,d \n ) \n ...' // returns ["A","b","c","d"]
'function (a,b)...' // returns ["a","b"]
'function $args(func) ...' // returns ["func"]
'null...' // returns ["null"]
'function Object() ...' // returns []
function $args(func) {
return (func + '')
.replace(/[/][/].*$/mg,'') // strip single-line comments
.replace(/\s+/g, '') // strip white space
.replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments
.split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters
.replace(/=[^,]+/g, '') // strip any ES6 defaults
.split(',').filter(Boolean); // split & filter [""]
}
// test cases
document.getElementById('console_info').innerHTML = (
[
// formatting -- typical
function(a,b,c){},
function(){},
function named(a, b, c) {
/* multiline body */
},
// default values -- conventional
function(a /* = 1 */, b /* = true */) { a = a||1; b=b||true; },
function fprintf(handle, fmt /*, ...*/) { },
// default values -- ES6
"function( a, b = 1, c ){}",
"function (a=4*(5/3), b) {}",
// embedded comments -- sardonic
function(a, // single-line comment xjunk) {}
b //,c,d
) // single-line comment
{},
function(a /* fooled you{*/,b){},
function /* are you kidding me? (){} */(a /* function() yes */,
/* no, */b)/* omg! */{/*}}*/},
// formatting -- sardonic
function ( A, b
,c ,d
)
{
},
// by reference
this.jQuery || function (a,b){return new e.fn.init(a,b,h)},
$args,
// inadvertent non-function values
null,
Object
].map(function(f) {
var abbr = (f + '').replace(/\n/g, '\\n').replace(/\s+|[{]+$/g, ' ').split("{", 1)[0] + "...";
return " '" + abbr + "' // returns " + JSON.stringify($args(f));
}).join("\n") + "\n"); // output for copy and paste as a markdown snippet
<pre id='console_info'></pre>
Solution 4
Solution that is less error prone to spaces and comments would be:
var fn = function(/* whoa) */ hi, you){};
fn.toString()
.replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg,'')
.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1]
.split(/,/)
["hi", "you"]
Solution 5
A lot of the answers on here use regexes, this is fine but it doesn't handle new additions to the language too well (like arrow functions and classes). Also of note is that if you use any of these functions on minified code it's going to go 🔥. It will use whatever the minified name is. Angular gets around this by allowing you to pass in an ordered array of strings that matches the order of the arguments when registering them with the DI container. So on with the solution:
var esprima = require('esprima');
var _ = require('lodash');
const parseFunctionArguments = (func) => {
// allows us to access properties that may or may not exist without throwing
// TypeError: Cannot set property 'x' of undefined
const maybe = (x) => (x || {});
// handle conversion to string and then to JSON AST
const functionAsString = func.toString();
const tree = esprima.parse(functionAsString);
console.log(JSON.stringify(tree, null, 4))
// We need to figure out where the main params are. Stupid arrow functions 👊
const isArrowExpression = (maybe(_.first(tree.body)).type == 'ExpressionStatement');
const params = isArrowExpression ? maybe(maybe(_.first(tree.body)).expression).params
: maybe(_.first(tree.body)).params;
// extract out the param names from the JSON AST
return _.map(params, 'name');
};
This handles the original parse issue and a few more function types (e.g. arrow functions). Here's an idea of what it can and can't handle as is:
// I usually use mocha as the test runner and chai as the assertion library
describe('Extracts argument names from function signature. 💪', () => {
const test = (func) => {
const expectation = ['it', 'parses', 'me'];
const result = parseFunctionArguments(toBeParsed);
result.should.equal(expectation);
}
it('Parses a function declaration.', () => {
function toBeParsed(it, parses, me){};
test(toBeParsed);
});
it('Parses a functional expression.', () => {
const toBeParsed = function(it, parses, me){};
test(toBeParsed);
});
it('Parses an arrow function', () => {
const toBeParsed = (it, parses, me) => {};
test(toBeParsed);
});
// ================= cases not currently handled ========================
// It blows up on this type of messing. TBH if you do this it deserves to
// fail 😋 On a tech note the params are pulled down in the function similar
// to how destructuring is handled by the ast.
it('Parses complex default params', () => {
function toBeParsed(it=4*(5/3), parses, me) {}
test(toBeParsed);
});
// This passes back ['_ref'] as the params of the function. The _ref is a
// pointer to an VariableDeclarator where the ✨🦄 happens.
it('Parses object destructuring param definitions.' () => {
function toBeParsed ({it, parses, me}){}
test(toBeParsed);
});
it('Parses object destructuring param definitions.' () => {
function toBeParsed ([it, parses, me]){}
test(toBeParsed);
});
// Classes while similar from an end result point of view to function
// declarations are handled completely differently in the JS AST.
it('Parses a class constructor when passed through', () => {
class ToBeParsed {
constructor(it, parses, me) {}
}
test(ToBeParsed);
});
});
Depending on what you want to use it for ES6 Proxies and destructuring may be your best bet. For example if you wanted to use it for dependency injection (using the names of the params) then you can do it as follows:
class GuiceJs {
constructor() {
this.modules = {}
}
resolve(name) {
return this.getInjector()(this.modules[name]);
}
addModule(name, module) {
this.modules[name] = module;
}
getInjector() {
var container = this;
return (klass) => {
console.log(klass);
var paramParser = new Proxy({}, {
// The `get` handler is invoked whenever a get-call for
// `injector.*` is made. We make a call to an external service
// to actually hand back in the configured service. The proxy
// allows us to bypass parsing the function params using
// taditional regex or even the newer parser.
get: (target, name) => container.resolve(name),
// You shouldn't be able to set values on the injector.
set: (target, name, value) => {
throw new Error(`Don't try to set ${name}! 😑`);
}
})
return new klass(paramParser);
}
}
}
It's not the most advanced resolver out there but it gives an idea of how you can use a Proxy to handle it if you want to use args parser for simple DI. There is however one slight caveat in this approach. We need to use destructuring assignments instead of normal params. When we pass in the injector proxy the destructuring is the same as calling the getter on the object.
class App {
constructor({tweeter, timeline}) {
this.tweeter = tweeter;
this.timeline = timeline;
}
}
class HttpClient {}
class TwitterApi {
constructor({client}) {
this.client = client;
}
}
class Timeline {
constructor({api}) {
this.api = api;
}
}
class Tweeter {
constructor({api}) {
this.api = api;
}
}
// Ok so now for the business end of the injector!
const di = new GuiceJs();
di.addModule('client', HttpClient);
di.addModule('api', TwitterApi);
di.addModule('tweeter', Tweeter);
di.addModule('timeline', Timeline);
di.addModule('app', App);
var app = di.resolve('app');
console.log(JSON.stringify(app, null, 4));
This outputs the following:
{
"tweeter": {
"api": {
"client": {}
}
},
"timeline": {
"api": {
"client": {}
}
}
}
Its wired up the entire application. The best bit is that the app is easy to test (you can just instantiate each class and pass in mocks/stubs/etc). Also if you need to swap out implementations, you can do that from a single place. All this is possible because of JS Proxy objects.
Note: There is a lot of work that would need to be done to this before it would be ready for production use but it does give an idea of what it would look like.
It's a bit late in the answer but it may help others who are thinking of the same thing. 👍
vikasde
Updated on June 23, 2021Comments
-
vikasde about 3 years
Is there a way to get the function parameter names of a function dynamically?
Let’s say my function looks like this:
function doSomething(param1, param2, .... paramN){ // fill an array with the parameter name and value // some other code }
Now, how would I get a list of the parameter names and their values into an array from inside the function?
-
vikasde about 15 yearsI have to many functions already pre-defined that are being called with standard parameters instead of a single object. Changing everything would take to much time.
-
vikasde about 15 yearsIsn't arguments deprecated? See the suggestion of Ionut G. Stan above.
-
user5880801 about 15 yearsvikasde is right. Accessing the
arguments
property of a function instance is deprecated. See developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… -
Lambder almost 12 yearsThis response is not the answer to the original question which was defined precisely. It shows a solution for completely different problem. The original question refers to the technique AngularJS uses fror its dependency injection. Argument names are meaningful as they correspond to dependencies of the module which DI automatically provides.
-
Andrej over 11 yearsAnd where are the names of function parameters?
-
bubersson over 11 yearsNote that this solution may fail because of comments and spaces - for example:
var fn = function(a /* fooled you)*/,b){};
will result in["a", "/*", "fooled", "you"]
-
CWSpear about 11 yearsThis and @Lambder's angular solution get the parameter names, but how do you get the values?
-
Raphael Schweikert about 11 yearsThis could be even more straightforward if you used
SomeFuncName
instead ofarguments.callee
(both point to the function object itself). -
JBarnes almost 11 years@bubersson You could use this in conjunction with the AngularJS code to strip comments shown in Lambder's answer in order to avoid comments breaking this.
-
bubersson almost 11 years@JBarnes Yes! I've also added that comment to the bottom of this page long time ago.
-
Jack Allan almost 11 yearsUpdated my example to include regex to strip comments
-
Aditya M P almost 11 years@apaidnerd with the blood of demons and spawn of satan, apparently. Regex?! Would be cool if there was a built in way in JS, wouldn't it.
-
B T almost 11 yearsI modified the function to return an empty array (instead of null) when there aren't any arguments
-
sasha.sochka almost 11 years@apaidnerd, so true! Just thought- how in the hell is that implemented? Actually I thought about using functionName.toString() but I hoped for something more elegant (and perhaps faster)
-
Cody over 10 yearsAh... You mean you want it in hash-form? As if:
var args = name.arguments; console.log('I WANNa SEE', args);
output something like "{arg1: {...}, arg2: 'string'}"? This might clear things up:(function fn (arg, argg, arrrrgggg) { console.log('#fn:', fn.arguments, Object.keys(fn.arguments)); }); fn('Huh...?', 'Wha...?', 'Magic...?');
. Function Arguments are an 'Array'-like object, having Enumerable indices. I don't think a hash-mapping is possible, but you could just pass an Object-literal in which is good practice if you have more than 4 params anyway. -
christianbundy about 10 yearsI'm curious, why is
STRIP_COMMENTS
outside of the scope of the function? I understand that it works, but is there any reason to do it that way? Great tool! -
Jack Allan about 10 yearsThere is a cost to compiling a regex, therefore you want to avoid compiling complex regexs more than once. This is why it is done outside the function
-
tgoneil about 10 yearsThe comment stripping regex can be siimplified, by observing that: '[\s\S]' can be replaced with '.' This is because a character class that matches any character in a set or it's complement will match any character. All of these regex's match any single character: '[\s\S]', [\w\W]', '[\d\D]' or '.' So, /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg can be replaced with /((\/\/.*$)|(\/*.*?*\/))/mg; jsfiddle.net/tgoneil/6K57R
-
tgoneil about 10 yearsCORRECTION: Was going to modify the regex with a /s modifier that perl allows so '.' can also match newline. This is necessary for multi-line comments inside /* */. Turns out Javascript regex doesn't allow the /s modifier. The original regex using [/s/S] does match newline characters. SOOO, please disregard the previous comment.
-
Hart Simha over 9 years@sasha.sochka, came here wondering the exact same thing, after realizing there was no built in way to get parameter names with javascript
-
Nick over 9 yearsto save people time , you can get this function from angular via
annotate = angular.injector.$$annotate
-
andes about 9 yearsI did a jsperf between this answer and a mod of the Angular JS answer - @jack-allen answer wins over Angular: jsperf.com/get-function-parameter-names.
-
andes about 9 yearsI did a jsperf between a mod of this answer and the chosen jack-allan answer - jack-allen answer wins over Angular: jsperf.com/get-function-parameter-names
-
Jack Allan about 9 years@andes Note you are including the regex compilation in your tests. These should only be done once. Your results may be different if you move the regex compilation to the setup step instead of the test
-
Jack Allan about 9 yearsUpdated with a hack to make the code work with ES6 default parameters
-
Shishir Arora almost 9 yearsCan we know the name of actual arguments passed in the function? like func(a,b,c,d); when we call this I want a,b,c,d printed in output
-
Jack Allan almost 9 years@Shishir that is what this function returns
-
Shishir Arora almost 9 years
-
Dennis Hackethal over 8 yearsIf you're already using Angular, you can use its
$injector
service:$injector.invoke(function(serviceA){});
-
Merlyn Morgan-Graham over 8 yearsThis breaks when one-line comments are present. Try this:
return (func+'') .replace(/[/][/].*$/mg,'') // strip single-line comments (line-ending sensitive, so goes first) .replace(/\s+/g,'') // remove whitespace
-
humbletim about 8 yearsGood catch -- I've updated the example with your suggested fix and also added a corresponding test case to the code snippet. Thanks!
-
Steven Hunt almost 8 yearsI literally went searching on the Internet for this topic because I was curious how Angular did it... now I know and also I know too much!
-
Andrew T Finnell almost 8 years@AlexMills One thing I've noticed is that the Spec for Arrow Functions says that they shouldnt be treated as 'functions.' Meaning it wouldn't be appropriate for this to match the array functions. The 'this' is not set the same way, and they shouldnt be invoked as functions either. It was something I learned the hard way. ($myService) => $myService.doSomething() looks cool, but it's a misuse of the Array Functions.
-
Paul Go over 7 yearsYou should probably replace
func + ''
withFunction.toString.call(func)
to defend against the case when the function has a custom .toString() implementation. -
humbletim over 7 yearsWas wondering how to defend against that and would like to incorporate your suggestion. Non-function values would still need to be coerced -- do you think it's worth aiming for compactness:
(/^f/.test(typeof func) ? $args.toString.call(func) : func+'')
, or in this case better to just spell it out:(typeof func === 'function' ? Function.toString.call(func) : func+'')
? -
Matt over 7 yearsfat arrows =>
.split(/\)[\{=]/, 1)[0]
-
James Drew over 7 yearsI think the case for something like this is usually: debugging/logging, some sort of decorator that does funky stuff (technical term 😁), or building a dependency injection framework for your apps to inject automatically based on argument name (this is how angular works). Another really interesting use case is in promisify-node (it's a library that takes a function that normally takes a callback and then converts it to a Promise). They use this to find common names for callbacks (like cb/callback/etc) and then they can check if the function is async or sync before wrapping it.
-
James Drew over 7 yearsSee this file for their parser. It's a bit naive but it handles the majority of cases.
-
Domino over 7 yearsInteresting, I'm surprised such a library got any attention. Well, there are multiple open issues about problematic situations like the ones I described. As I said, if it's for debugging purposes it's fine, but relying on string conversion of functions in production environments is way too risky.
-
Domino over 7 yearsOn a "funny" sidenote, you can make all functions act as if they were anonymous built-ins by running this:
Function.prototype.toString = function () { return 'function () { [native code] }'; };
-
James Drew over 7 yearsAgreed, it's a bit messy to handle it like this. The best and most straightforward use is dependency injection. In that case you own the code and can handle naming and other areas of code. I think this is where it would see the most use. Im currently using esprima (instead of regex) and ES6
Proxy
(constructor trap and apply trap) andReflection
to handle DI for some of my modules. It's reasonably solid. -
James Drew over 7 yearsThere is a little bit of me that would love to include this in an angular app and see how long it takes our developers to debug it. 😈😁 Might be a good one for a long interview question! 🤔
-
Avinash about 7 yearsWith ES6 arrow functions having single argument like (a => a*10) it fails to give desired output.
-
Robin F. about 7 yearsthe es6 stuff is all nice but in a prod env we're still having transpiled code to es5 which means the default params are within the function declared on top (see babel)
-
myzhou about 7 yearsThat example is just to get the parameters' name for you.
-
chharvey over 6 yearsThis answer is useful, but it does not answer the question. I voted up because it solved my problem, but I think it should be moved somewhere more appropriate. Perhaps search for related questions?
-
George 2.0 Hope over 6 yearsThe while loop results in an infinite loop with the code provided (as of 20171121at1047EDT)
-
Ates Goral over 6 years@George2.0Hope Thanks for pointing that out. I'll update the answer.
-
George 2.0 Hope over 6 yearsargs.toSource is not a function (line 20) ... but even if you change it to: console.log(args.toString()); ... you get ... [object Object] ... better if you do : console.log(JSON.stringify(args));
-
Ates Goral over 6 yearsThings have changed quite a bit since 2009!
-
Hearen over 6 years@Jack Allan I truly have no idea - the answer is not to the question actually. The question is asking about how to get the parameter
names
inside of the function when the functioninvoked
instead ofdefined
. I currently just met the same issue (trying to detect the method by the parameter name and then pass the parameter value to the name-oriented method). But weirdly enough is that it's up voted by most people. Perhaps it's well-coded but actually not helping the question. Thank you. -
balupton over 6 years
function gotcha (a, b = false, c) {}; alert(gotcha.length)
-
Magnus about 6 yearsIn chrome, the above getParamNames(...) function just returns an array with the string 'e' inside. Just tried it and got
0: "e"
in the dev console. Any idea why? -
Individual11 about 6 yearsin case anyone shows up here for React, this function, which is awesome, will not work in strict mode.
-
Michael Theriot almost 6 yearsI would not use this in production; default parameters have too many problems with this kind of approach. For example,
getParamNames(function (a = function (b = 4, c = 5) {}){})
reports["a", "c"]
. A safer way would be to leverage an abstract syntax tree rather than regular expressions. -
pwilcox almost 6 yearsif I'm not mistaken, in your browser version, the first conditional in FUNC_ARGS will work for both arrow and traditional functions, so you don't need the second part and so you can do away with the dependency on ARROW.
-
cue8chalk over 5 yearsThis is great! I was looking for a solution like this that uses a parser to cover ES6 syntax. I’m planning on using this to create a jest “implements interface” matcher because simply using function.length has limitations with default parameters, and I wanted to be able to assert rest parameters.
-
Dale Anderson over 5 yearsIt is worth pointing out that the fifth test case that contains parentheses in the default value currently fails. I wish my regex-fu was strong enough to fix, sorry!
-
Michael Auderer almost 5 yearsthis splits destructured objects (like
({ a, b, c })
) into all the parameters inside the destructuring. to keep destructured objects intact, change the last.split
to:.split(/,(?![^{]*})/g)
-
Tim Pozza almost 5 years
let var = [...arguments]
... for param values, updated to reflect ES6 and later. Just sayin'. -
Jack Allan almost 5 yearsA few people have said this doesn't actually answer the question. And that the actual question is how can I know the names of the variables that were used in the function call that invoked my function? I did not assume that to be the question because it is a really bad idea for any language to allow such a thing to be possible. For a start the function call might be made with literals instead of variables. Also any language that allows this would not allow the programmer to keep the implementation details of a function hidden. This makes any kind of real programming totally impractical. So to
-
Jack Allan almost 5 years(Continued)So to anyone finding my answer expecting it to answer this question and not what I assumed the question was I offer this advice: what you are trying to do is most certainly a bad idea and there is no doubt in my mind that, even if it were possible -which thankfully it is not- there are zero good reasons to do this. Please re evaluate your problem because you're not solving it correctly.
-
eran otzap over 4 yearswhat about the values ?
-
charlie roberts over 4 yearsquite nice. one line, handles arrow functions, no external dependencies, and covers more than enough edge cases, at least for my intended use. if you can make some reasonable assumptions about the function signatures you'll be dealing with this is all you'll need. thanks!
-
A T over 4 yearsDoesn't work with this simple arrow function:
f = (a, b) => void 0
; ongetParameters(f)
I getTypeError: Cannot read property '1' of null
-
A T over 4 yearsThanks, yours is the only one in this thread which worked for me.
-
ZomoXYZ over 4 years@AT I have just updated the answer to fix support for your issue
-
A T over 4 yearsThanks… but keep in mind that parentheses are no longer required, so you can do things like
getParameters(a => b => c => d => a*b*c*d)
, which with your code still gives thatTypeError: Cannot read property '1' of null
… whereas this one works stackoverflow.com/a/29123804 -
Dmitri over 4 yearsDoes not work when function has default values (role, name="bob") The extracted parameter is name="bob" instead of expected "name"
-
Jelle De Loecker about 4 yearsThis will also not work when there are default string values that contain "//" or "/*"
-
Dan O over 3 yearsseems to fail for inline comments containing a close-paren, e.g.
function foo(x, y /* FIXME: (temp), z */, w) {
-
Michael A. Vickers over 3 yearsI tried to edit but "suggested edit queue is full". You can fix the issue reported by Dan O by moving the "replace(/\/*.**\//, '')" in the return statement near the bottom to the end of the "string = func.toString()" declaration near the top. Make sure to keep the trim() in the return statement.
-
Kai Lehmann over 3 yearsI have a function with parameter destructing like function ({test = '22'} = {}) {return test;}. $args() gives me an output of ['{test']. could you fix that. Thank you :)
-
Melab about 3 yearsDoes it put a list of a function's parameter names inside the function?
-
SanBen about 3 years@Melab getMetadata('design:paramtypes', x) will only return the types, as an example [String]
-
S.Serpooshan almost 3 yearsThis dosen't work for many cases, including any code with newline char (\r\n), and any func code that includes
(
and)
chars inside its function body! eg:myFunc(p1, p2) { if(p1>0){} }
-
Mike 'Pomax' Kamermans over 2 yearshere's a good reason: having a superclass with async functions verify that a subclass in fact implements those same functions as
async
instead of bare, so that it can throw an error on instantiation, rather than much later when code tries to invoke the offending function. You want the error to say which function that is, and sure, you could omit the arguments, but it makes for an easier code dive if you see the full function signature instead. Is this niche? incredibly, yeah. Is it a valid use-case? Also yes ;) -
Zack Morris over 2 years@DaleAnderson hey you're right, and it threw me for a moment until I re-read my answer. It's failing for the browser version because it uses a regex, while the Node.js example uses the
babylon
parser. So you correctly identified the limitations of regex, the main one being (if I recall) that a regex can't process recursive/nested structures. If you search for(note that it stops at the first complex default value)
that's what I meant by that. Sorry for the inconvenience!