JavaScript Object.freeze — What gets logged?
This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Object Freeze Immutability and improve your technical interview readiness.
const obj = { a: 1 }
Object.freeze(obj)
obj.a = 99
console.log(obj.a)
Detailed Explanation
Why This Question Matters
If you've spent any time with JavaScript, you know that objects are mutable by default. You can add properties, delete them, or change their values on the fly. Usually, that's a feature. But in a large codebase, mutability is often where bugs hide. You pass an object to a function, and suddenly some distant piece of code has changed a value you relied on.
That's why Object.freeze() exists. It's the nuclear option for immutability.
The reason this specific snippet trips people up is that JavaScript handles "failed" assignments differently depending on whether you're running in Sloppy Mode or Strict Mode. If you don't know which one you're in, you're basically guessing how the engine will react to a frozen object.
Understanding the Code
Let's look at the snippet again:
Here is the play-by-play of what's happening under the hood:
1. const obj = { a: 1 }: We create an object. Using const here only means the variable obj cannot be reassigned to a new object. It does *not* stop the properties inside the object from being changed.
2. Object.freeze(obj): This is where the magic happens. JavaScript marks this object as non-extensible. It locks the properties. You can't add new ones, you can't delete existing ones, and—crucially—you can't change the values of existing ones.
3. obj.a = 99: We attempt to overwrite the value of a. Since the object is frozen, the JavaScript engine says "No."
4. console.log(obj.a): We print the value.
Finding the Correct Answer
The correct answer is 1.
Why? Because the assignment obj.a = 99 fails. In a standard script (Sloppy Mode), JavaScript simply ignores the assignment and moves to the next line. It doesn't throw an error; it just fails silently. Since the value of a was never actually updated, it remains 1.
Now, if this code were wrapped in "use strict"; or inside an ES6 module (which are strict by default), the result would be different. Instead of silently failing, JavaScript would throw a TypeError: Cannot assign to read only property 'a' of object. In that case, the console.log would never even execute because the script would crash.
Common Mistakes Developers Make
The biggest mistake is confusing const with Object.freeze().
I see this all the time with juniors. They think that because they declared an object with const, the object is immutable. It isn't. const only protects the *binding*. You can still mutate the internals of a const object all day long. If you want the data to be locked, you need Object.freeze().
Another common trap is thinking Object.freeze() is recursive. It isn't. It performs a shallow freeze.
Check this out:
If you have nested objects, you have to freeze every single level manually or use a library like Immer.js.
Real-World Usage
In production, you don't often see Object.freeze() used on every single variable—that would be a nightmare to manage. However, it's incredibly useful for Configuration Objects or Enums.
If you have a set of global constants for your app—like API endpoints or status codes—you want to ensure that no rogue piece of logic accidentally changes STATUS.PENDING to something else mid-session.
By freezing this, you're creating a "read-only" contract. It makes the code more predictable and prevents a whole category of state-related bugs.
Key Takeaways
const prevents variable reassignment; Object.freeze() prevents object mutation.Object.freeze() is shallow. Nested objects remain mutable unless you freeze them specifically.TypeError.Why this matters
Understanding Object Freeze Immutability is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.