10

Can somebody please explain to me why this simple piece of code is not working?

var user = {
    get name() {
        return this.name;
    },    
    set name(value) {
        this.name = value;
    }
};
user.name = 'David';

When I put this in the Firebug console in Firefox 21.0 it gives me this error:

InternalError: too much recursion
this.name = value;

Why? What is the proper way to define getters and setters in Javascript?

David Barreto
  • 8,887
  • 7
  • 32
  • 46
  • You are recursively calling name() ad infinitum, hence the error "too much recursion" – stackErr Jun 17 '13 at 15:33
  • 1
    The problem is that you're trying to set a property called "name" inside your setter. What will that do? It'll call the setter, which will try to set a property called "name". What will that do? ... – Pointy Jun 17 '13 at 15:33
  • 2
    The problem is that `this.name = value;` triggers the function `set name(value)` which sets `this.name = value;`, which triggers the function `set name(value)` ... I could go on. – Felix Kling Jun 17 '13 at 15:33
  • 1
    @StephenKennedy They do exists as native features. Plus your comment is way off topic. – Aadit M Shah Jun 17 '13 at 15:35

3 Answers3

14

When you attempt to set name, the function will set this.name = value.

But the function is now attempting to set name. Therefore it will call the function again and set this.name to value.

But the function is now attempting to set name. Therefore it will call the function again and set this.name to value.

But the function is now attempting to set name. Therefore it will call the function again and set this.name to value.

....... SOME TIME LATER .......

But the function is now attempting to set name. Therefore it will call the function again and set this.name to value.

But the browser has determined that the call stack is too deep, the function has called itself too many times, and therefore to prevent a complete crash it causes the function to fail with the error you see.


Try using a different property name, such as this._name, to store and retrieve the value.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • You gotta love recursion. Thank God this is not possible in Lua. Otherwise you would have an infinite loop that would never even throw an error. Tail call optimization FTW. – Aadit M Shah Jun 17 '13 at 15:33
  • I call this the Vicious Möbius Strip. It's like a vicious circle, but with only one side to it ;) – Niet the Dark Absol Jun 17 '13 at 15:36
  • It's more like the vicious toroidal array. You come out from one side and end up on the other side and keep doing that until you finally realize that you're running in circles and give up. – Aadit M Shah Jun 17 '13 at 15:38
  • So Javascript getters and setters don't behave like the "magic" setters (__set) and getters (__get) methods found in PHP for example? There is no recursion problems there. See [this](http://stackoverflow.com/questions/4478661/getter-and-setter) – David Barreto Jun 17 '13 at 15:45
14

Your setter is calling itself.

Here's a solution :

var user = {
    get name() {
        return this._name;
    },    
    set name(value) {
        this._name = value;
    }
};
user.name = 'David';

Side note : Be careful that the get and set operators aren't supported in IE8.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    For [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FWorking_with_Objects#Defining_getters_and_setters)... – Brad Christie Jun 17 '13 at 15:34
5

Try,

var user = {
    get name() {
        return this._name;
    },    
    set name(value) {
        this._name = value;
    }
};
user.name = 'David';

Note the use of _name instead of name. Setting the value of name in the setter of name is a recursive call, hence the exception.

chuckj
  • 27,773
  • 7
  • 53
  • 49