...

View Full Version : can you enumerate local variables?



david_kw
02-03-2007, 10:28 PM
I was wondering if it is possible to find the names of all the local variables.

Like



function func() {
var x = 5;
var y = 8;

// some code

for (key in func.local) {
alert(key + "=" + func.local['key']);
}
}


and you'd get two alerts
x=5 and y=8

Is anything like that or similar possible? I know you can get the arguments with the argument[] object.

Thanks,
david_kw

liorean
02-03-2007, 11:16 PM
Nope. The variable object is not available from script in any way, except for the global object or objects used in with statements.

There have been some JavaScript engines that exposed all locals as named properties of the function object (only while the function was running however), but nothing you can rely on.

chump2877
02-03-2007, 11:33 PM
The closest I can think of to acheive something like that is this:


<script type="text/javascript">

function whatever()
{
var obj = new Object;

obj.x = 5;
obj.y = 8;

for (var prop in obj)
{
alert(prop + "=" + obj[prop]);
}
}

</script>

<input type="button" value="click me" onclick="whatever();" />

...make the object a local "variable" and iterate through the property/value pairs in the object...

david_kw
02-04-2007, 12:01 AM
Hmm, bummer. Ok thanks a lot. Saves me a lot of time searching even more for something that doesn't exist.

david_kw

david_kw
02-04-2007, 07:58 AM
Well I came up with a hack sort of way to do it. In case you are wondering why I wanted this functionality, I am trying to put together a better closure breakpoint (I hate the IE debugger, thank god for FireBug) like

http://trimpath.com/project/wiki/TrimBreakpoint

Basically, I found that arguments.callee is the function, so I do a toString() on it then parse it for variable names. I have no doubt some might slip by my parsing depending on how it is declared, but it seems to get most of them (at least the way I declare them).

Here's the code to parse the function in case you are interested



function getLocals(args) {
var ret = [];
var reArg = /\(?\s*(\w+)\s*(,|\))/g;
var reHasVar = /\Wvar\W/;
var reGetVar = /(var|,)\s*(\w+)/g;
var a = args.callee.toString().split("\n");
var lookForArgs = true;
var reResult;

ret.push(a[0]); // save the function name for later use

for (var i = 0; i < a.length; i++) {
if (lookForArgs) {
while ((reResult = reArg.exec(a[i])) != null) {
ret.push(reResult[1]);
}
if (/\{/.test(a[i])) {
lookForArgs = false;
}
}
if (!lookForArgs) {
if (reHasVar.test(a[i])) {
while ((reResult = reGetVar.exec(a[i])) != null) {
ret.push(reResult[2]);
}
}
}
}

return(ret);
}


It's called like
getLocals(arguments);
and returns an array of arguments and local variable names which I can iterate through using eval to get the values.

Thanks again. I imagine without your help I'd still be searching the web for some way it is exposed by the browser.

david_kw

david_kw
03-14-2007, 09:02 PM
For anyone interested. I fixed a few bugs in my getLocals function and made it more flexible when searching for variables. Here is the code plus a working example.



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Enumerate Local Variables</title>
<script type="text/javascript">
/* <![CDATA[ */
function indexInLiteral(str, index) {
var inStrLiteral = 0;
var inObjLiteral = 0;
var inArrayLiteral = 0;

for (var i = 0; i < str.length; i++) {
if (inStrLiteral) {
if (str.charAt(i) == "'" || str.charAt(i) == '"') {
inObjLiteral--;
}
} else {
if (str.charAt(i) == "'" || str.charAt(i) == '"') {
inObjLiteral++;
}
}
if (!inStrLiteral) {
if (inObjLiteral) {
if (i == index) {
return (true);
}
if (str.charAt(i) == "}") {
inObjLiteral--;
}
} else {
if (str.charAt(i) == "{") {
inObjLiteral++;
}
}
if (inArrayLiteral) {
if (i == index) {
return (true);
}
if (str.charAt(i) == "]") {
inArrayLiteral--;
}
} else {
if (str.charAt(i) == "[") {
inArrayLiteral++;
}
}
}
}

return (false);
}

function getLocals(args) {
var ret = [];
var reArg = /\(?\s*(\w+)\s*(,|\))/g;
var reEndArg = /\{/;
var reHasVar = /(\W|^)var\W/;
var reGetVar = /(var|,)\s*(\w+)/g;
var a = args.callee.toString().split("\n");
var lookForArgs = true;
var reResult;

ret.push(a[0]); // save the function name for later use

for (var i = 0; i < a.length; i++) {
if (lookForArgs) {
reArg.lastIndex = 0;
while ((reResult = reArg.exec(a[i])) != null) {
ret.push(reResult[1]);
}
reEndArg.lastIndex = 0;
if (reEndArg.test(a[i])) {
lookForArgs = false;
}
}
if (!lookForArgs) {
reHasVar.lastIndex = 0;
if (reHasVar.test(a[i])) {
reGetVar.lastIndex = 0;
while ((reResult = reGetVar.exec(a[i])) != null) {
if (!indexInLiteral(a[i], reResult.index)) {
ret.push(reResult[2]);
}
}
}
}
}

return (ret);
}

var array_of_locals;
var str, e;
function doIt(s) {
var adiv = document.getElementById("adiv");
var x = 5, y = 9;
var re = /^test$/;

array_of_locals = getLocals(arguments);

str = "Variables for ";
for (var i = 0; i < array_of_locals.length; i++) {
if (i == 0) {
str += array_of_locals[i] + "<br/>";
} else {
str += "&nbsp;&nbsp;" + array_of_locals[i] + " = " + eval(array_of_locals[i]) + "<br/>";
}
}

adiv.innerHTML = str;
}
/* ]]> */
</script>
</head>
<body>
<div>
<button onclick="doIt('This is junque...');">Do it</button>
<br />
<div id="adiv"> </div>
</div>
</body>
</html>


david_kw



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum