Suggest an editImprove this articleRefine the answer for “Object.preventExtensions() in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`Object.preventExtensions()` forbids adding new properties to an object but still allows changing and deleting the existing ones.** It is the softest form of protection: the `configurable`, `writable` and `enumerable` descriptors are left untouched, and you can check the state with `Object.isExtensible(obj)`, which returns `false`. Properties inherited through the prototype are not affected. ```javascript const user = { name: 'Alice', age: 25 }; Object.preventExtensions(user); user.city = 'Kyiv'; // will not be added delete user.age; // can be deleted user.name = 'Oleh'; // can be changed console.log(user); // { name: 'Oleh' } ``` **Key point:** the method "closes the door" to new properties and restricts nothing else.Shown above the full answer for quick recall.Answer (EN)Image**`Object.preventExtensions()` is a built-in JavaScript method that forbids adding new properties to an object while still allowing you to change and delete the existing ones.** It is the softest form of object protection, unlike `seal()` and `freeze()`. ## Theory ### TL;DR - `Object.preventExtensions(obj)` forbids **adding** new properties. - Existing properties **can be changed** and **can be deleted**. - The `configurable`, `writable` and `enumerable` descriptors are left unchanged. - To check the state: `Object.isExtensible(obj)` returns `false`. - The ban also covers `Object.defineProperty()`, which throws a `TypeError`. - Properties inherited through the prototype stay available. ### Quick example ```javascript const user = { name: 'Alice', age: 25 }; Object.preventExtensions(user); user.city = 'Kyiv'; // will not be added delete user.age; // can be deleted user.name = 'Oleh'; // can be changed console.log(user); // { name: 'Oleh' } ``` After `Object.preventExtensions()`: - new properties **cannot be added**; - old ones **can be deleted**; - existing values **can be changed**. ### Syntax and checking the state ```javascript Object.preventExtensions(obj) ``` | Argument | Description | | --- | --- | | `obj` | The object that **will not accept new properties** | It returns the object itself, already non-extensible, so it is not a copy. ```javascript console.log(Object.isExtensible(user)); // false ``` `Object.isExtensible(obj)` returns `false` when new properties cannot be added to the object. The operation is irreversible: an object can never be made extensible again. ### What happens under the hood `Object.preventExtensions(obj)` does the following: - forbids adding new properties, including through `Object.defineProperty()`; - existing properties **stay writable and deletable**; - `configurable`, `writable` and `enumerable` are not touched. An attempt to add a property through `defineProperty` does not stay quiet, it throws: ```javascript const obj = {}; Object.preventExtensions(obj); try { Object.defineProperty(obj, 'x', { value: 1 }); } catch (err) { console.log('Error:', err.message); } ``` It prints: ```javascript Error: Cannot define property x, object is not extensible ``` A plain assignment `obj.x = 1` behaves differently: in sloppy mode it silently does nothing, while under `'use strict'` it throws a `TypeError` as well. ### Differences from seal() and freeze() | Method | Can add | Can delete | Can change | The `configurable` descriptors | | --- | --- | --- | --- | --- | | `preventExtensions()` | No | Yes | Yes | Unchanged | | `seal()` | No | No | Yes | All `configurable: false` | | `freeze()` | No | No | No | All `configurable: false`, `writable: false` | So `preventExtensions()` is the **softest protection option**. It simply "closes the door" but does not get in the way of working with what is already there. ### Prototypes and inherited properties ```javascript const parent = { role: 'user' }; const child = Object.create(parent); Object.preventExtensions(child); child.name = 'Alice'; // will not be added console.log(child.name); // undefined console.log(child.role); // "user", inherited from the prototype ``` `preventExtensions()` does not affect **inherited properties**, they stay reachable through the prototype. Only the set of the object's **own** properties is restricted; the prototype itself, unless you protect it separately, can still be extended, and the new fields become visible to `child` immediately. Summary table: | Behaviour | Allowed? | | --- | --- | | Adding new properties | No | | Deleting existing ones | Yes | | Changing values | Yes | | Changing descriptors | Yes | | Check | `Object.isExtensible(obj)` | ### Common mistakes - **Expecting the object to become immutable.** `preventExtensions()` blocks neither writes nor `delete`; for that you need `seal()` or `freeze()`. - **Expecting an exception from a plain assignment.** `obj.x = 1` fails silently in sloppy mode; you only see the error under `'use strict'` or from `Object.defineProperty()`. - **Hoping to roll the protection back.** An object cannot be made extensible again, the state is irreversible. - **Forgetting about the prototype.** Only own properties are protected; adding fields to the prototype still affects the object. - **Treating the effect as deep.** Nested objects remain fully extensible and have to be handled separately.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.