Getting All Variables In Scope

Getting All Variables In Scope

Is there a way to get all variables that are currently in scope in javascript?

Solutions/Answers:

Solution 1:

No. “In scope” variables are determined by the “scope chain”, which is not accessible programmatically.

For detail (quite a lot of it), check out the ECMAScript (JavaScript) specification. Here’s a link to the official page where you can download the canonical spec (a PDF), and here’s one to the official, linkable HTML version.

Update based on your comment to Camsoft

The variables in scope for your event function are determined by where you define your event function, not how they call it. But, you may find useful information about what’s available to your function via this and arguments by doing something along the lines of what KennyTM pointed out (for (var propName in ____)) since that will tell you what’s available on various objects provided to you (this and arguments; if you’re not sure what arguments they give you, you can find out via the arguments variable that’s implicitly defined for every function).

So in addition to whatever’s in-scope because of where you define your function, you can find out what else is available by other means by doing:

var n, arg, name;
alert("typeof this = " + typeof this);
for (name in this) {
    alert("this[" + name + "]=" + this[name]);
}
for (n = 0; n < arguments.length; ++n) {
    arg = arguments[n];
    alert("typeof arguments[" + n + "] = " + typeof arg);
    for (name in arg) {
        alert("arguments[" + n + "][" + name + "]=" + arg[name]);
    }
}

(You can expand on that to get more useful information.)

Related:  google.maps.places is undefined

Instead of that, though, I’d probably use a debugger like Chrome’s dev tools (even if you don’t normally use Chrome for development) or Firebug (even if you don’t normally use Firefox for development), or Dragonfly on Opera, or “F12 Developer Tools” on IE. And read through whatever JavaScript files they provide you. And beat them over the head for proper docs. 🙂

Solution 2:

Although everyone answer “No” and I know that “No” is the right answer but if you really need to get local variables of a function there is a restricted way.

Consider this function:

var f = function() {
    var x = 0;
    console.log(x);
};

You can convert your function to a string:

var s = f + '';

You will get source of function as a string

'function () {\nvar x = 0;\nconsole.log(x);\n}'

Now you can use a parser like esprima to parse function code and find local variable declarations.

var s = 'function () {\nvar x = 0;\nconsole.log(x);\n}';
s = s.slice(12); // to remove "function () "
var esprima = require('esprima');
var result = esprima.parse(s);

and find objects with:

obj.type == "VariableDeclaration"

in the result (I have removed console.log(x) below):

{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "x"
                    },
                    "init": {
                        "type": "Literal",
                        "value": 0,
                        "raw": "0"
                    }
                }
            ],
            "kind": "var"
        }
    ]
}

I have tested this in Chrome, Firefox and Node.

Related:  Chain multiple “then” in jQuery.when

But the problem with this method is that you just have the variables defined in the function itself. For example for this one:

var g = function() {
    var y = 0;
    var f = function() {
        var x = 0;
        console.log(x);
    };
}

you just have access to the x and not y.
But still you can use chains of caller (arguments.callee.caller.caller.caller) in a loop to find local variables of caller functions. If you have all local variable names so you have scope variables. With the variable names you have access to values with a simple eval.

Solution 3:

Yes and no. “No” in almost every situation. “Yes,” but only in a limited manner, if you want to check the global scope. Take the following example:

var a = 1, b = 2, c = 3;

for ( var i in window ) {
    console.log(i, typeof window[i], window[i]);
}

Which outputs, amongst 150+ other things, the following:

getInterface function getInterface()
i string i // <- there it is!
c number 3
b number 2
a number 1 // <- and another
_firebug object Object firebug=1.4.5 element=div#_firebugConsole
"Firebug command line does not support '$0'"
"Firebug command line does not support '$1'"
_FirebugCommandLine object Object
hasDuplicate boolean false

So it is possible to list some variables in the current scope, but it is not reliable, succinct, efficient, or easily accessible.

A better question is why do you want to know what variables are in scope?

Solution 4:

In ECMAScript 6 it’s more or less possible by wrapping the code inside a with statement with a proxy object. Note it requires non-strict mode and it’s bad practice.

function storeVars(target) {
  return new Proxy(target, {
    has(target, prop) { return true; },
    get(target, prop) { return (prop in target ? target : window)[prop]; }
  });
}
var vars = {}; // Outer variable, not stored.
with(storeVars(vars)) {
  var a = 1;   // Stored in vars
  var b = 2;   // Stored in vars
  (function() {
    var c = 3; // Inner variable, not stored.
  })();
}
console.log(vars);

The proxy claims to own all identifiers referenced inside with, so variable assignments are stored in the target. For lookups, the proxy retrieves the value from the proxy target or the global object (not the parent scope). let and const variables are not included.

Related:  Asynchronously load images with jQuery

Inspired by this answer by Bergi.

Solution 5:

You can’t.

Variables, identifiers of function declarations and arguments for function code, are bound as properties of the Variable Object, which is not accesible.

See also:

Solution 6:

As everyone noticed: you can’t.
But you can create a obj and assign every var you declare to that obj.
That way you can easily check out your vars:

var v = {}; //put everything here

var f = function(a, b){//do something
}; v.f = f; //make's easy to debug
var a = [1,2,3];
v.a = a;
var x = 'x';
v.x = x;  //so on...

console.log(v); //it's all there