Question presented to candidate: "JavaScript has three levels of object lockdown — Object.preventExtensions, Object.seal, and Object.freeze. What exactly does each one actually block, and what's still genuinely allowed at each level?"
What a strong answer should cover:
- 📌 Interview term: a real, three-level immutability spectrum —
preventExtensionsis the loosest (blocks only adding new properties);sealadds blocking delete and reconfigure;freezeis the strongest, additionally blocking changing existing values. - 📌 Verified, not assumed — the exact real capability matrix:
preventExtensionsgenuinely still allowed deleting an existing property, changing its value, AND reconfiguring it — only adding a new property was genuinely blocked.sealadditionally genuinely blocked delete and reconfigure, but changing an existing value's genuinely still worked.freezegenuinely blocked all four operations. - A precise answer names that all three levels also genuinely make the object non-extensible (
Object.isExtensible()returns realfalsefor all three) — extensibility is the one thing every level shares. - 📌 A genuine, easy-to-miss gotcha, verified directly:
Object.isSealed()andObject.isFrozen()both genuinely returntruefor an empty, non-extensible object — even one that only went throughpreventExtensions(), never actually sealed or frozen — because "every own property is non-configurable" is vacuously true when there are genuinely zero properties to check. - A precise answer names the practical use case each level fits:
preventExtensionsfor "no new fields, but internal bookkeeping can still change";sealfor "a fixed shape whose values can still update" (a real, common pattern for a validated config object with mutable values);freezefor genuine full immutability.
Clarifying questions expected:
- "Does the actual requirement need existing values to remain updatable, or does absolutely nothing about this object need to change after creation?" — directly decides between
sealandfreeze. - "Is the concern specifically about accidentally adding typo'd properties (a common real bug), or about the object's shape and values both needing to stay fixed?" — decides whether
preventExtensionsalone is genuinely sufficient.
Code / implementation expected: Yes — a real, per-capability matrix (can-add / can-delete / can-change-value / can-reconfigure) run separately against fresh objects at each of the three levels is the concrete, convincing proof of exactly where each level's real boundary sits.