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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.