Create immutable object in javascript
Asked Answered
A

6

13

I have a routine where I receive some data from an api. I'd like to store this data in an object, but after that i want to "lock" this object and not allow any change to the properties or their values after that point. Is that possible? (If possible using only ES5).

Aquarium answered 20/10, 2017 at 16:20 Comment(2)
you mean like constEnsiform
@palaѕн OP wants to keep it ES5 onlyDivisionism
M
26

If you wish for an object to not be able to be modified you can use Object.freeze.

The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed, it also prevents the prototype from being changed. The method returns the object in a frozen state.

If you simply want to prevent a variable from being reassigned you can use const (ES6), however note that:

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.

E.g, the following is perfectly valid

const a = { x: 7 }
a.x = 9
console.log(a.x) // 9

However, trying to reassign a variable declared with const will throw a TypeError:

const a = 5
a = 7
Merola answered 20/10, 2017 at 16:22 Comment(7)
This won't prevent you from re-assigning a different value to a var.Sycophant
technically the const variable is not mutable. It's const. The object the variable is referencing is mutable but the variable is not and can not be changed to reference a different object.Undone
Object.freeze was kinda good enough, but i fell into a different problem: Before freezing my object i assign those values to a different var and then freeze the original var. When i tried to remove itens from the second var(not freezed) it raised this error (angular.js:13294 TypeError: Cannot add/remove sealed array elements at Array.splice (<anonymous>))Yakutsk
Thats probably due to those vars referencing the same memory space. Any idea on that second issue (Guess i should open a new question)Yakutsk
To my knowledge, Object.freeze enforces immutability only up to 1 level.Randellrandene
@ArunkumarSrisailapathi, correct. You’d have to do this for the nested objects as wellMerola
@ViníciusMussato you should not assign the second var to the original var. it does not make a copy of the original object, it only copies the reference of the first object. if you want a copy of the original object use const a={ c:1, d:2 }; const b=Object.assign({},a); Object.freeze(a); delete b.d; Stanleigh
S
6

For Immutable object we can use below approches

  1. Object.freeze()
  2. To enforce object immutability while update the object make sure to
  3. use Object.assign({},a,{foo:'bar'}) rather than a.foo='bar'
  4. we can use spread(...) operator.

See example:

var person={name:'pavan',age:26}

var newPerson={...person,name:'raju'}

console.log(newPerson ===person) //false
console.log(person)  //{name:'pavan',age:26}
console.log(newPerson)  //{name:'raju',age:26}
Snowfall answered 3/4, 2018 at 7:45 Comment(0)
S
0

No. There's no good way to enforce const-ness is ES5.

Sycophant answered 20/10, 2017 at 16:23 Comment(3)
Not sure why you'd think Object.freeze from ES5 is not a good solution to the OP's question. The OP said they wanted the object locked down and said nothing about reassigning a variable, which is all that const does. I reread the OP's question several times and think freezing it is exactly what they have in mind. Cheers.Rocher
@RayToal If you look at the edit history of the question, you'll see that the version that I answered asked: "Id'like to store this data in a var, but after that i want to "lock" this var". A subsequent edit changed the meaning of the OP's question and invalidated the answer.Sycophant
Oh dear thank you I did not see that the question was edited. Locking a var is certainly different that making the object immutableRocher
S
0

You can use Object.freeze() method which freezes an object. A frozen object can no longer be changed and prevents :

  • New properties from being added to it
  • Existing properties from being removed
  • Changing the enumerability, configurability, or writability of existing properties
  • The values of existing properties from being changed.

Demo :

const obj = {
  name: 'Alpha',
  age: 30,
  hobbies: ['reading', 'writing']
};

Object.freeze(obj);

obj.name = 'Beta';
obj.hobbies[0] = 'painting'; 

console.log(obj.name); // Alpha (It works fine with the properties which contains primitive values)
console.log(obj.hobbies[0]); // painting (It does not work for nested objects/array)

If you see in above code snippet, It works fine with the properties which contains primitive values but it is updating the values of nested object/array.

Hence, You can try as const If you are working with typescript in your requirement. It will freeze the whole object along with the nested properties with object/array.

Shorten answered 9/6, 2022 at 14:0 Comment(0)
B
0

If you separate you code into pure and impure parts (as with functional core, imperative shell), you can get by in the pure parts using objects and arrays and not, as a matter of discipline, mutating them.

I've done this for years and have a library which aids this style of development. I can't imagine needing the insurance policy of having to Object.freeze everything. Now, eventually, when records and tuples is adopted into the spec you can just use them instead!

Birthroot answered 18/1, 2023 at 19:15 Comment(0)
K
0

You can use Object.freeze() + get method (accessor properties)

const obj = {
  label: 'Jim',
  leisures: ['gaming', 'work out'],
  get toys(){
    return ['ball', 'car']
  },
};

Object.freeze(obj);

obj.label = 'Dwight'; // immutable
obj.leisures[0] = 'coding';  // mutable
obj.toys[0] = 'axe';  // immutable

console.log(obj.label); // Jim 
console.log(obj.leisures[0]); // coding 
console.log(obj.toys[0]); // ball, because the `get` method makes toys() accesible, but isnt mutable. 
Ketonuria answered 12/10, 2023 at 20:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.