larrydalmeida
larrydalmeida

Reputation: 1620

Uncaught TypeError: Cannot assign to read only property

I was trying out this really simple example from the awesome "Professional JavaScript for Web Developers" book by Nicholas Zakas but I can't figure what I am doing wrong here. Must be something really simple that I missed but I'm stuck.

Here is the code:

'use strict';

var book = {};

Object.defineProperties(book, {
    originYear: {
        value: 2004,
        writable: false
    },

    _year: {
        value: 2004
    },

    edition: {
        value: 1
    },

    year : {
        get: function() {
            return this._year;
        },

        set: function(newValue) {
            if(newValue > this.originYear) {
                this._year = newValue;
                this.edition += newValue - this.originYear;
            }
        }
    }
});

console.log(book.edition);
book.year = 2006;
console.log(book.edition);

The error I am getting on the Chrome console is:

Uncaught TypeError: Cannot assign to read only property '_year' of #main.js:31 Object.defineProperties.year.setmain.js:39 (anonymous function)

Can someone please explain where I have gone wrong?

Here is the fiddle

Upvotes: 91

Views: 371458

Answers (4)

Greggory Wiley
Greggory Wiley

Reputation: 961

I had this issue with a Nextjs React setup. If I fired a state setting function it would happen on re-render (firing an onClick function), but not if I loaded the page directly or via refresh. Making a copy of the non editable, or in my case "frozen" object before modifying parameters fixed the problem for me. I was passing an object in Via json and then trying to set some additional properties of it.

book = {...book} 
book.year = 2006;

My own setup looked more like this,

let linkStyle={}
if (appearance.LinkStyle) {
 linkStyle = apperance.LinkStyle
}

linkStyle.color = appearance.primaryColor // Same Error here

Resolved by

let linkStyle={}
if (appearance.LinkStyle) {
  linkStyle = {...apperance.LinkStyle}
}

linkStyle.color = appearance.primaryColor

Upvotes: 5

Ramkumar
Ramkumar

Reputation: 31

If sometimes a link! will not work. so create a temporary object and take all values from the writable object then change the value and assign it to the writable object. it should perfectly.

var globalObject = {
    name:"a",
    age:20
}
function() {
    let localObject = {
    name:'a',
    age:21
    }
    this.globalObject = localObject;
}

Upvotes: 1

Leo
Leo

Reputation: 13828

When you use Object.defineProperties, by default writable is set to false, so _year and edition are actually read only properties.

Explicitly set them to writable: true:

_year: {
    value: 2004,
    writable: true
},

edition: {
    value: 1,
    writable: true
},

Check out MDN for this method.

writable
true if and only if the value associated with the property may be changed with an assignment operator.
Defaults to false.

Upvotes: 67

Rutwick Gangurde
Rutwick Gangurde

Reputation: 4912

I tried changing year to a different term, and it worked.

public_methods : {
    get: function() {
        return this._year;
    },

    set: function(newValue) {
        if(newValue > this.originYear) {
            this._year = newValue;
            this.edition += newValue - this.originYear;
        }
    }
}

Upvotes: 0

Related Questions