DEV Community

Ricardo Luz
Ricardo Luz

Posted on

The problem with Object.freeze

In several situations, we need to ensure that some Object values and methods won’t change anymore; some examples are:

  • A list with access keys to external web services
  • An object with a unique ID that represents the user or current session
  • Information about the user device like the operating system, browser version and name and more.

To solve problems like this my first approach was relying upon in Object.freeze function, let’s take an example:

const myCustomObj = {  
  thisObjectWillChange: "nope ",  
};  

Object.freeze(myCustomObj);  

myCustomObj.thisObjectWillChange = "trying change this 🤔";  

console.log(myCustomObj.thisObjectWillChange); // will return: nope

Enter fullscreen mode Exit fullscreen mode

So far so good, it worked as we expected, but something works weird when we increase the number of branches of our object tree-like in this example:

const accessKeys = {  
  aws: {  
   accessKeyId: 'abc123',  
   secretAccessKey: 'secretValue'  
 },  
 google: 'gogole123'  
}
Object.freeze(accessKeys);
accessKeys.aws.accessKeyId = 'trying to change this value 😰';

console.log(accessKeys.aws.accessKeyId); // will return 'trying to change this value 😰'

Enter fullscreen mode Exit fullscreen mode

So, what’s happened wrong? Why the Object.freeze won’t prevent this alteration? When we check the MDN Documentation we found the answer:

What is “shallow freeze”?

The result of calling Object.freeze(object) only applies to the immediate properties of object itself and will prevent future property addition, removal or value re-assignment operations only on object. If the value of those properties are objects themselves, those objects are not frozen and may be the target of property addition, removal or value re-assignment operations.

The problem isn’t only editing the value, but is also possible add new attributes and delete the current attributes in other branches except for the root, in this branches is like we don’t have anything froze, terrible right?

To solve this we need to apply the Object.freeze again in these branches, something like this:

const accessKeys = {  
  aws: {  
   accessKeyId: 'abc123',  
   secretAccessKey: 'secretValue'  
 },  
 google: 'gogole123'  
}
Object.freeze(accessKeys);  
Object.freeze(accessKeys.aws);
accessKeys.aws.accessKeyId = 'trying to change this value';
console.log(accessKey.aws.accessKeyId); ***//will return 'abc123'* 😃**
Enter fullscreen mode Exit fullscreen mode

But you know, if you have many subattributes could be hard to freeze all inner branches, to help us to make it easier we have the method Object.getPropertyNames available, with this method we get the keys of each branch, and we could navigate inside our object using recursion:

Now the only task left is to freeze each branch of our tree:

If you to want to know more about Javascript I recommend these books:

  • You Don’t Know JS Serie by Kyle Simpson (My favourite)
  • Eloquent JS by Marijn Haverbeke
  • Head First Javascript by Michael Morrison
  • Secrets of the JavaScript Ninja by Bear Bibeault and John Resig

Ricardo Luz (@_rxluz) | Twitter

Thanks for reading! Feel free to hit the recommend if you found this article helpful.

Top comments (0)