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) { _x000D_
return (func + '')_x000D_
.replace(/[/][/].*$/mg,'') // strip single-line comments_x000D_
.replace(/\s+/g, '') // strip white space_x000D_
.replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments _x000D_
.split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters _x000D_
.replace(/=[^,]+/g, '') // strip any ES6 defaults _x000D_
.split(',').filter(Boolean); // split & filter [""]_x000D_
} _x000D_
_x000D_
// test cases _x000D_
document.getElementById('console_info').innerHTML = (_x000D_
[ _x000D_
// formatting -- typical _x000D_
function(a,b,c){}, _x000D_
function(){}, _x000D_
function named(a, b, c) { _x000D_
/* multiline body */ _x000D_
}, _x000D_
_x000D_
// default values -- conventional _x000D_
function(a /* = 1 */, b /* = true */) { a = a||1; b=b||true; }, _x000D_
function fprintf(handle, fmt /*, ...*/) { }, _x000D_
_x000D_
// default values -- ES6 _x000D_
"function( a, b = 1, c ){}", _x000D_
"function (a=4*(5/3), b) {}", _x000D_
_x000D_
// embedded comments -- sardonic _x000D_
function(a, // single-line comment xjunk) {}_x000D_
b //,c,d_x000D_
) // single-line comment_x000D_
{}, _x000D_
function(a /* fooled you{*/,b){}, _x000D_
function /* are you kidding me? (){} */(a /* function() yes */, _x000D_
/* no, */b)/* omg! */{/*}}*/}, _x000D_
_x000D_
// formatting -- sardonic _x000D_
function ( A, b _x000D_
,c ,d _x000D_
) _x000D_
{ _x000D_
}, _x000D_
_x000D_
// by reference _x000D_
this.jQuery || function (a,b){return new e.fn.init(a,b,h)},_x000D_
$args, _x000D_
_x000D_
// inadvertent non-function values _x000D_
null, _x000D_
Object _x000D_
].map(function(f) {_x000D_
var abbr = (f + '').replace(/\n/g, '\\n').replace(/\s+|[{]+$/g, ' ').split("{", 1)[0] + "...";_x000D_
return " '" + abbr + "' // returns " + JSON.stringify($args(f));_x000D_
}).join("\n") + "\n"); // output for copy and paste as a markdown snippet
_x000D_
<pre id='console_info'></pre>
_x000D_