6

Why is that Object.freeze(obj) is made to fail silently when obj is mutated?

Wouldn't it be more logical to throw than error when an immutable object is mutated? Then, it would be to the user's discretion if he wants to wrap a try catch around his Object.freeze(obj). Similar to how we need to wrap JSON.parse() with try catch to avoid errors with empty strings or malformed JSON's.

I wish if the community can make a comment.

Edit after few answers and comments:

It is understood that Object.frozen() throws error in strict mode. But why is it necessary for the method to fail silently in non-strict mode?

kvn
  • 2,210
  • 5
  • 20
  • 47
  • Taken from MDN " Any attempt to do so will fail, either silently or by throwing a TypeError exception (most commonly, but not exclusively, when in strict mode)." – Kira Mar 03 '17 at 09:16
  • MDN link: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze Your question is not in sync with the description part of this link – Kira Mar 03 '17 at 09:18
  • The intent of the question is to understand why is it made to fail silently when it is meant to be immutable and any applicable use cases if possible. It is understood that it throws error in strict mode. – kvn Mar 03 '17 at 09:20
  • Object.freeze will just freeze an object. That is, you cannot change the values of properties inside a frozen object. If you attempt to change the value, then it will fail silently. But your question says "Object.freeze(obj) is made to fail" – Kira Mar 03 '17 at 09:37
  • Possible duplicate of [Is there a way to make an “Object.frozen” object throw warnings when an attempt is made to change it?](https://stackoverflow.com/questions/9119655/is-there-a-way-to-make-an-object-frozen-object-throw-warnings-when-an-attempt) – Bergi Jul 04 '20 at 14:04

2 Answers2

6

Object.freeze() does throw, in strict mode.

In strict mode, the following program will throw any time a property is added, mutated or deleted on the frozen object.

Assume we have

'use strict'

const obj = Object.freeze({ test: true })

Error when adding a property:

obj.other = true
// TypeError: Can't add property another, object is not extensible

Mutating an existing property throws:

obj.test = false
// TypeError: Cannot assign to read only property 'test' of object '#<Object>'

Deleting a property throws:

delete obj.test
TypeError: Cannot delete property 'test' of #<Object>

If would like to understand strict mode in more detail (highly recommended) have a look at the official MDN docs for the differences.

The opinions on this topic vary - one would expect mutations of the object to throw because "you are doing something you should not be doing" while others might say that if you Object.freeze() something, you just want to prevent any modifications to it. And that you successfully accomplish. If it caused applications to crash on mutations, programmers would have no choice but to either check all objects they did not create for their frozenness or they would have to wrap all such operations in try/catch block. This is simply too much to ask.

Note about try/catch

You can avoid wrapping property manipulations in try/catch blocks simply by checking the object's temperature :

if (Object.isFrozen(obj)) {
  // Can't touch this!
}
Robert Rossmann
  • 11,931
  • 4
  • 42
  • 73
  • In my understanding, the objects which are frozen would be something like global immutable constants and the developer knows what they are. Using `Object.frozen()` for just every object is a bad practise and there is no question of using `Object.isFrozen()` in every line. `Object.freeze()` is something like `const` in ES6. The dev knows that the object is a global constant and shouldn't be changed, but if he still tries to go around the rule, he should get an error. – kvn Mar 03 '17 at 16:44
  • It is not the case of using `const` or `Object.frozen()` for every variable/object and checking if it is mutable or not. The intent of the question is to understand the necessity of silent fail in non-strict mode. – kvn Mar 03 '17 at 16:47
  • I do not think there is a "necessity" - the decision was most likely made due to ergonomics. As you said yourself, it is not feasible to use `Object.isFrozen()` everywhere, therefore it is more ergonomic to just have the operation silently fail. – Robert Rossmann Mar 03 '17 at 17:27
  • Say `Object.frozen()` throws errors in non-strict mode, the developer wouldn't use it to freeze every object. If he wants to, then that should be left to his discretion. The interpreter should be responsible of raising an alarm for faulty code. You wouldn't want to reassign a `const` variable and have it unchanged. – kvn Mar 04 '17 at 00:38
  • Note that it does not matter whether `Object.freeze()` is called in strict mode – Lokomotywa Sep 04 '19 at 10:46
-2

I think this is why modifying a frozen object fails silently,

If error is thrown, execution of code will stop. Try and catch statements are available to handle the error. Is it okay to use try and catch statements for every line in your code to avoid the error? I think no

1. Unnecessary use of try and catch blocks in code

Let's say an object is frozen at some point in the flow of control. There maybe many lines in code which try to add a new property or modify the value of an existing property in the frozen object. In this scenario, if error is thrown, then you need to add try and catch blocks in all those lines of code.

2. Any number of objects can be freezed

Let's say more than one object is freezed. This will increase the need for more try and catch statements. It may lead to enclosing each line of your code with a try and catch block

Kira
  • 1,403
  • 1
  • 17
  • 46