Inspect the names/values of arguments in the definition/execution of a JavaScript function
Asked Answered
D

5

20

I'm looking to do the equivalent of Python's inspect.getargspec() in Javascript.

I do know that you can get the arguments list from a Javascript function, but what I'm really looking for is the names of the arguments from the originally defined function.

If this is in fact impossible, I'm going to have to 'brute-force' it by getting the string of the function, i.e. myFunc.toString() and then parsing out the ... inside of function myFunc(...). Does anyone know how to do this parsing in a general way?

Thanks for any tips.

Deeplaid answered 27/5, 2009 at 10:14 Comment(0)
T
24

While I can't see any good reason for this,

var reg = /\(([\s\S]*?)\)/;
var params = reg.exec(func);
if (params) 
     var param_names = params[1].split(',');

assuming func is the name of your function

Taco answered 27/5, 2009 at 10:28 Comment(8)
Nice, thanks! I do have some good reasons for this :) ...and they are mostly related to wanting to replicate some working Python code that uses inspect.getargspec(), in JavaScript.Deeplaid
I'm still wondering though if this is the only way of doing such an inspection... there is no more elegant way?Deeplaid
nothing that I know of, no. It's certainly not a common way to do things in JavaScript.Taco
Note that it doesn't play well at all with minifiers that change variable names, so you should be really carefull when using this kind of hacks.Laxative
@Grégoire: Honestly, it isn't a practice I'd advocate at all, but the OP question was fairly clear and this is the only way of getting those argument names. If a minifier is used, all you'll get is the new minified names, which, hopefully, should still be enough.Taco
You would need to know parameter names or function names, etc .. if you were building a tool that manipulates the code itself, such as a debugger, or dynamic code generators. The mimifier problem might then be handled using source maps.Parthia
The only reason not to go that route is if you anticipate the developer might include comments in the parameter definitions. Another answer includes handling for this possibility.Farmhand
Can't your regexp just be simplified to /\((.*)\)/ ?Doehne
S
5

The following function will return an array of parameter names of any function passed in.

function getParamNames(func) {
    var funStr = func.toString();
    return funStr.slice(funStr.indexOf('(')+1, funStr.indexOf(')')).match(/([^\s,]+)/g);
}

Example usage:

getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
Syrup answered 29/3, 2012 at 11:44 Comment(0)
D
4

here a small nodejs module for that.

https://github.com/kilianc/node-introspect

Druse answered 22/11, 2011 at 10:3 Comment(0)
M
0

Here's a version that uses higher order functions. The only thing I don't like about it is that you have to specify parameters as members of an array. But at least they only have to be specified once.

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var withNamedParams = function(params, lambda) {
    return function() {
        var named = {};
        var max   = arguments.length;

        for (var i=0; i<max; i++) {
            named[params[i]] = arguments[i];
        }

        return lambda(named);
    };
};

var foo = withNamedParams(["a", "b", "c"], function(params) {
    for (var param in params) {
        alert(param + ": " + params[param]);
    }
});

foo(1, 2, 3);
</script>
</head>
<body>

</body>
</html>
Merlenemerlin answered 18/6, 2009 at 9:14 Comment(0)
S
-1

Sightly improved version of Jonathan Fingland's answer:

// Utility function to extract arg name-value pairs
function getArgs(args) {
    var argsObj = {};

    var argList = /\(([^)]*)/.exec(args.callee)[1];
    var argCnt = 0;
    var tokens;

    while (tokens = /\s*([^,]+)/g.exec(argList)) {
        argsObj[tokens[1]] = args[argCnt++];
    }

    return argsObj;
}

// Test subject
function add(number1, number2) {
    var args = getArgs(arguments);
    alert(args.toSource()); // ({number1:3,number2:4})
}

// Invoke test subject
add(3, 4);

Note: This only works on browsers that support arguments.callee.

(Also posted at How to get function parameter names/values dynamically from javascript)

Smith answered 17/6, 2009 at 19:18 Comment(1)
This is not good because you have to run the function to get its arguments. The question was to get arguments from the definition.Laxative

© 2022 - 2024 — McMap. All rights reserved.