3

Are there any ability to get closure variables list (Ok, maybe all scope variables) in JavaScript?

Sample:

function factory(){
    var _secret = "Some secret";
    return function(code){
        // How to get parent function variables names here? 
        // ...
    }
}

var inside = factory();

inside();
Michael Plakhov
  • 2,292
  • 2
  • 19
  • 21

5 Answers5

2

Assuming this is for debugging purposes, you can try parsing the function body and evaluating identifiers found:

function getvars(fn, _eval) {
    var words = String(fn).replace(/".*?"|'.*?'/g, '').match(/\b[_A-Za-z]\w*/g),
        ret = {}
    words.forEach(function(w) {
        try { ret[w] = _eval(w) } catch (e) {};
    });
    return ret;
}

function factory() {
    var _secret = "Some secret";
    var _other = "Other secret";

    return function(code){
        var vars = getvars(factory, _ => eval(_));
        return vars;
    }
}


vars = factory()();
document.write('<pre>'+JSON.stringify(vars,0,3));

Needless to say, this is an extremely naive way to deal with code, so handle it with care.

georg
  • 211,518
  • 52
  • 313
  • 390
  • 1
    I like this solution. I am newbie. Could please give some information about following expression?: _ => eval(_) – Tornike Shavishvili Feb 05 '16 at 12:46
  • In my situation I have my js code running in closure of other lib function (my code will be evaluated) so your solution looks good (Yes i need this just for debugging). Main issue is to find the name of this outer function. – Michael Plakhov Feb 05 '16 at 12:56
  • 1
    @blindProgrammer this is ES6 arrow functions https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions – Michael Plakhov Feb 05 '16 at 12:57
  • 1
    @blindProgrammer: we need to pass "eval" to `getvars` so that it will be aware of the local bindings. Since `eval` is special, we can't pass it directly, and have to wrap it in a function - in this case as a "fat arrow" one. – georg Feb 05 '16 at 12:57
1

There's no comprehensive way to get a list of all variables in scope. You could enumerate over the this object, but that will still only give you a list of the enumerable objects on this, and even at that there will still be things like function arguments that aren't on this.

So no, this cannot be done. Also check out this similar question.

Community
  • 1
  • 1
Matthew
  • 4,149
  • 2
  • 26
  • 53
1

No, it isn't possible. ECMAScript specification doesn't expose Enviroment Record objects to end user anywhere.

Ginden
  • 5,149
  • 34
  • 68
1

One way to see them is using console.dir to get all the scopes including closures scopes and their variables list. Example:

function factory(){
    var _secret = "Some secret";
    var i = 0;
    return function(){
        i++;    
        return _secret + i;
    }
}

var inside = factory();
inside(); // "Some secret1"
inside(); // "Some secret2"
console.dir(inside); // It shows you all variables in [[Scopes]] > Closure

Image of how you would see the console:

console.dir output

It works in Chromium based browsers.

Edit: Related answer with nested scopes in related question https://stackoverflow.com/a/66896639/2391782

Johann Echavarria
  • 9,695
  • 4
  • 26
  • 32
-1

Since the primary concept of a closure is scope, and vars inside a closure are private, there can be no way to achieve this without exposing them somehow, like via a method.

What are you really trying to achieve?

DvS
  • 1,025
  • 6
  • 11