Search code examples
javascriptoopgetter-setter

Can setters modify non-writable/non-configurable properties?


I have been reading about property attributes (configurable, writable, enumerable) and am looking for some clarification on how setters interact with non-writable / non-configurable properties.

Specifically, if a property is defined using Object.defineProperty(), it will default to configurable: false and writable: false. In this case, would a setter function within the same object still be able to modify the value of the property?

This is the example that I'm looking at:

var book = {};

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

-- From "Professional JavaScript for Web Developers, 3rd Ed." (Nicholas C Zakas)

So, the setter part of book.year is meant to update the value of book._year.

But since book._year is defined using Object.defineProperty and not explicitly set to be either writable or configurable, shouldn't not be modifiable? Or are functions within the same object (ie book.year) somehow excluded from those restrictions?

It is also worth noting that this code gives me some funny results when I run it in the browser... Namely: book.year = 2005 does nothing to either book.year or book._year, and book.year(2005) results in TypeError: book.year is not a function.


Solution

  • There are no exclusions about writable true/false for self properties. If you have a non writable property then there is no way to change from wherever you wanted to do it. Except for configurable values when you can change descriptor to writable.

    Another issue about TypeError:
    setter function in property definition using `defineProperty` is a hidden method that invokes when you assign the property. That's not an actual function from outside.

    You can see it's execution by debugging when you assign a value to this property