5

Python's locals() function, when called within the scope of a function, returns a dictionary whose key-value pairs are the names and values of the function's local variables. For example:

def menu():
    spam = 3
    ham = 9
    eggs = 5

    return locals()

print menu()  # {'eggs': 5, 'ham': 9, 'spam': 3}

Does JavaScript have anything like this?

kjo
  • 33,683
  • 52
  • 148
  • 265

2 Answers2

4

The scope itself isin't accessible in JavaScript, so there's no equivalent. However you could always declare a private variable that acts as a local scope if you absolutely need this kind of feature.

function a() {
    var locals = {
        b: 1,
        c: 2
    };

    return locals;
}

Also, if the reason you wanted to use something like locals() is to inspect the variables, you have other solutions such as setting break points withing your browser's development tools and add watches. Putting debugger; directly in the code will also work in some browsers.

plalx
  • 42,889
  • 6
  • 74
  • 90
2

No, there is nothing like that in Javascript functions, but there is a way to accomplish something very similar using this to define all the properties on an object, instead of as local variables:

function menu(){
  return function(){

    this.spam = 3;
    this.ham = 9;
    this.eggs = 5;

    // Do other stuff, you can reference `this` anywhere.
    console.log(this); // Object {'eggs': 5, 'ham': 9, 'spam': 3}

    return this; // this is your replacement for locals()
  }.call({});
}

console.log(menu()); // Object {'eggs': 5, 'ham': 9, 'spam': 3}
Paul
  • 139,544
  • 27
  • 275
  • 264
  • This pattern would only work when you do not need to rely on another `this` value, which makes it quite verbose for very little flexibility in my opinion. – plalx Sep 18 '13 at 02:46
  • 1
    -1 for using [`new function(){…}`](http://stackoverflow.com/questions/10406552/is-it-right-to-think-of-a-javascript-function-expression-that-uses-the-new-key). It does not what you expect. – Bergi Sep 18 '13 at 02:54
  • 1
    @Bergi It does exactly what I want. It creates a new object every time `menu` is called. That object serves the purpose of being the dictionary that the OP wanted. – Paul Sep 18 '13 at 02:56
  • 1
    @Paulpro: It does more than you want. It creates an instance of an anonymous function expression (with a custom prototype), which is rubbish. Use a simple object literal instead: `function menu(){ var o={spam:3,ham:9,eggs:5}; console.log(o); return o; }` – Bergi Sep 18 '13 at 03:12
  • 1
    @Bergi I don't see the problem with that, unless the OP's intention was to use `menu` as a constructor, which it doesn't look like from their question. – Paul Sep 18 '13 at 03:14
  • 1
    The returned object holds unnecessary garbage, namely the `.constructor` property (try `console.log(new (menu().constructor));`). If you want to use `this` for some reason, use `.call` on an IEFE. – Bergi Sep 18 '13 at 03:18
  • 1
    @Bergi I really don't see a problem with the existance of the `constructor` property. It's not like it's a memory leak. But you're right, that is a better way which I hadn't thought of. Thanks – Paul Sep 18 '13 at 03:26
  • 1
    @Bergi, well that's not really an argument since an object literal also has a constructor property that points to `Object`, `console.log(new ({}).constructor);`, however I agree that it's a misuse of the `new` operator since you ignore most of it's effects, such as setting up the prototype chain. The issue is more that it's an overly complex solution that gives even less flexibility than using a simple object literal. Even `menu.call({});` would be too much. – plalx Sep 18 '13 at 03:26
  • 1
    @plalx: The point was that `menu().constructor` is not the common `Object` function… Depending on the variables in the `menu` scope, it might indeed produce a memory leak. – Bergi Sep 18 '13 at 03:37
  • 1
    @Bergi, Right, that's what I tought after writing my comment. However I am not sure that I see how a leak could be produced? – plalx Sep 18 '13 at 12:12
  • 1
    @plalx: With the constructor function living on the object, the `menu` scope cannot be garbage collected before the object. This is unintentional - a leak. Of course it's not noticeable unless a huge number of `menu()` objects is constructed (and not destroyed immediately), and the scope contains large values. Still, the pattern should be despised as a bad practise. – Bergi Sep 18 '13 at 12:23