0

SO I have two "name" as a property and as an parameter passed on Object.defineProperty(). If I choose to put naming convention same on as "name" for my book object as well Object.defineProperty() I am getting an error call "Stack size exceeds " on console. What is the exact difference between two? and how does it matters.

var book ={
  year: 2004,
  edition : 1
};

    Object.defineProperty(book, "year",{
      get: function(){
        return this.year;
      },
      set:function(newValue){
        if(newValue > 2004){
          this.year = newValue;
          this.edition = this.edition + newValue -2004;
        }
      }
    });

    book.year = 2005;
    alert(book.edition);

Thank you

user2864740
  • 60,010
  • 15
  • 145
  • 220
Megh
  • 145
  • 9
  • "Stack size exceeds" -> infinite recursion. In particular, get:year calls get:year (this.year) calls.. (the same problem occurs for the set). To fix this use a closed over variable or a *different* property name to store the underlying value. – user2864740 Jul 14 '15 at 23:46
  • Look how they do it on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) – epascarello Jul 14 '15 at 23:56

1 Answers1

1

You can't have both a getter for a property and expect to refer to a stored property by the same name. It's one or the other.

This creates an infinite loop:

Object.defineProperty(book, "year",{
    get: function(){
        return this.year;
    },
...

You're essentially saying that anytime someone requests the year property, then it should use your getter function. And, inside the getter function, you call the getter function again which calls the getter function again ... forever until the stack blows up. This statement return this.year will simply call the getter function.

Oh, and FYI, you have the same issue in your setter function too.


If you want a place to store the year property value, then you will have to either use a different property name or use some sort of closure variable (e.g.a private instance value). You cannot have both a getter and setter and a property of the name that you actually store the value in. It's one or the other.


A simple solution would be to just change the name of the property value where you store the actual value and then discourage any code from directly accessing that value:

var book ={
  _year: 2004,
  edition : 1
};

    Object.defineProperty(book, "year",{
      get: function(){
        return this._year;
      },
      set:function(newValue){
        if(newValue > 2004){
          this._year = newValue;
          this.edition = this.edition + newValue -2004;
        }
      }
    });

    book.year = 2005;
    alert(book.edition);
jfriend00
  • 683,504
  • 96
  • 985
  • 979