1

I got an error while use this code

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 += newValue - 2004;
            }
        }
    });

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

The warning told me that the error happened at Object.set [as year]this.year = newValue; I am confused that why setting the year will cause this error?

0

3 Answers 3

1

When you set the year property, you implicitly call the set function.

The set function sets the year property (if the value is > 2004).

So:

  1. You set the year property to 2005
  2. The set function sets the year property to 2005
  3. GOTO 2 and loop for infinity
Sign up to request clarification or add additional context in comments.

Comments

0

You're defining a getter and a setter for year. The setter, when assigning to this.year = newValue; invokes the setter again, which leads to an infinite loop. You would need to define a custom property _year for example, and keep your year state there:

var book = {
    edition: 1
};

Object.defineProperty(book, "_year", {
    value: 2004,
    enumerable: false, // Hide it when looping the object
    writeable: true,
    configurable: true
});

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

        if (newValue > 2004) {
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    },
    enumerable: true, // Show this when looping
    configurable: true
});

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

console.log(Object.keys(book)); // ['edition', 'year']

Comments

0

Here's the sequence of events that's causing this error:

  • You set the year of the book.
  • Since it's a property, the value gets passed to your setter function.
  • The check gets performed - since in this case it's true, year gets set.
  • Uh oh - since you just set year, the setter gets run again.
  • The check continues to pass, since it's receiving the same value over and over.
  • Your browser starts looping forever, runs out of memory, and falls over in a big heap.

To avoid this, you need to store the actual value in a separate field of the object (e.g. this._year), and then have your getter return that value. Here's an example:

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 += newValue - 2004;
        }
    }
});

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.