Uncaught TypeError: Cannot assign to read only property

Javascript

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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;
}

Solution 3 - Javascript

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;
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlarrydalmeidaView Question on Stackoverflow
Solution 1 - JavascriptLeoView Answer on Stackoverflow
Solution 2 - JavascriptRamkumarView Answer on Stackoverflow
Solution 3 - JavascriptRutwick GangurdeView Answer on Stackoverflow