Cannot assign to read only property of Object in JavaScript

avatar
Borislav Hadzhiev

Last updated: Mar 6, 2024
5 min

banner

# Cannot assign to read only property of Object in JavaScript

The error "Cannot assign to read only property of object" occurs when we try to change a property of an object that has been frozen or when a property has been defined with Object.defineProperties().

To solve the error, create a copy of the object or array, or set the property to writable.

cannot assign to read only property error

Here are 3 examples of how the error occurs.

index.js
// ๐Ÿ‘‡๏ธ With OBJECTS ๐Ÿ‘‡๏ธ const obj = { name: 'James', }; Object.freeze(obj); // โ›”๏ธ Error: Cannot assign to read only property 'name' of object '#<Object>' obj.name = 'Alice'; // ------------------------------------------------------ // ๐Ÿ‘‡๏ธ With ARRAYS ๐Ÿ‘‡๏ธ const arr = ['a', 'b', 'c']; Object.freeze(arr); // โ›”๏ธ Error: Cannot assign to read only property '0' of object '[object Array]' arr[0] = 'z'; // ------------------------------------------------------ // ๐Ÿ‘‡๏ธ With Object.defineProperties() ๐Ÿ‘‡๏ธ const obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', // ๐Ÿ‘‰๏ธ must be set writable: true // writable: true, // ๐Ÿ‘ˆ๏ธ uncomment this }, }); // โ›”๏ธ Error: Cannot assign to read only property 'country' of object '#<Object>' obj2.country = 'Austria';
The code for this article is available on GitHub

The first two errors occur because the object or array has been frozen with the Object.freeze() method.

# Common causes of the error

The most common causes of the error are:

  1. Trying to assign a property to a frozen object or array.
  2. Forgetting to set writable to true when using Object.defineProperties.
  3. Trying to modify a state object or array in place when using a third-party library, such as React.js.

# Creating a copy of the array or object

A frozen object can no longer be changed but you can create a copy of the array or object and change the copy.

index.js
// โœ… With OBJECTS const obj = { name: 'James', }; Object.freeze(obj); const objCopy = {...obj}; // ๐Ÿ‘ˆ๏ธ create copy objCopy.name = 'Alice'; console.log(objCopy); // ๐Ÿ‘‰๏ธ {name: 'Alice'} // -------------------------------------- // โœ… With ARRAYS const arr = ['a', 'b', 'c']; Object.freeze(arr); const arrCopy = [...arr]; // ๐Ÿ‘ˆ๏ธ create copy arrCopy[0] = 'z'; console.log(arrCopy); // ๐Ÿ‘‰๏ธ ['z', 'b', 'c']

creating copy of the array or object

The code for this article is available on GitHub

We used the spread syntax (...) to create a copy of the object and the array, so we can change them.

# Trying to sort a read-only array

The error also occurs when you try to sort a read-only array because the Array.sort() method sorts the array in place.

index.js
const arr = ['a', 'b', 'c']; Object.freeze(arr); // โ›”๏ธ TypeError: Cannot assign to read only property '0' of object '[object Array]' arr.sort();

To solve the error, create a copy of the array and sort the copy.

index.js
const arr = ['a', 'b', 'c']; Object.freeze(arr); // ๐Ÿ‘‡๏ธ create copy const arrCopy = [...arr]; // ๐Ÿ‘‡๏ธ sort the copy arrCopy.sort(); console.log(arrCopy); // ๐Ÿ‘‰๏ธ [ 'a', 'b', 'c' ]

create copy of array and sort the copy

The code for this article is available on GitHub

We used the spread syntax (...) to create a copy of the array and called the sort() method on the copy.

Now we no longer are trying to mutate a read-only array.

You can also use the Array.slice() method to create a shallow copy of the frozen array.

index.js
const arr = ['a', 'b', 'c']; Object.freeze(arr); // ๐Ÿ‘‡๏ธ create a shallow copy of the array const arrCopy = arr.slice(); arrCopy.sort(); console.log(arrCopy); // ๐Ÿ‘‰๏ธ [ 'a', 'b', 'c' ]

using array slice to create shallow copy of the frozen array

When the slice() method is called without any arguments, it returns a shallow copy of the original array.

# Set writable to true if using Object.defineProperties()

If you get the error when using the Object.defineProperties() method, set the property to writable if you want to change its value.

index.js
const obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', writable: true, // ๐Ÿ‘ˆ๏ธ set property to writable }, }); obj2.country = 'Austria'; console.log(obj2.country); // ๐Ÿ‘‰๏ธ "Austria"

set writable to true if using object define properties

The code for this article is available on GitHub

The country property is set to writable, so it can be changed.

The writable parameter defaults to false when using the Object.defineProperties() method.

If you want to be able to change the value of a property, explicitly set writable to true.

Other properties you may have to set on the object are configurable and enumerable:

  • configurable - if false, the property cannot be deleted or changed. Defaults to false.
  • enumerable - if true, the property is iterated over in loops. Defaults to false.
  • writable - if false, the value of the property cannot be changed
index.js
const obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', writable: true, // ๐Ÿ‘ˆ๏ธ set property to writable configurable: true, enumerable: true, }, }); console.log(obj2); obj2.country = 'Austria'; console.log(obj2.country); // ๐Ÿ‘‰๏ธ "Austria"
The code for this article is available on GitHub

We also set the enumerable and configurable properties to true.

  • When configurable is set to true, the property can be deleted. The default value of the property is false.

  • When enumerable is set to true, the property is iterated over in loops. The default value of the property is false.

Want to learn more about using the Object.defineProperty() method? Check out these resources: How to Add a Key/Value pair to an Object in JavaScript,How to Rename an Object Key in JavaScript,How to Clear an Object in JavaScript.

# Passing an object to the Object.freeze method

If you pass an object or an array to Object.freeze, you can't:

  • add new properties or elements to it
  • remove existing properties
  • change existing properties

The best way to get around this is to create a copy of the object or array and change the copy.

# Using a third-party library with frozen state objects and arrays

If you use some third-party library that has frozen a state object or array, chances are you aren't supposed to be mutating the state object directly.

The library probably exports a method that should be used to change the state.

When using libraries such as React.js, the state shouldn't be modified directly.

Instead, the library provides methods and hooks that can be used to change the state.

If objects you get from a library are marked as read-only, then that was done intentionally as they shouldn't be directly modified by the user.

Here are guides on how to change a state array or a state object when using React.js:

# Conclusion

To solve the "Cannot assign to read only property of object" error:

  1. Make sure to create a copy of the frozen object or array before setting a property.
  2. Set the writable property to true if you use Object.defineProperties.
  3. Make sure to not modify state objects in libraries such as React.js and use the built-in methods to set the state.
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev