Suggest an editImprove this articleRefine the answer for “Clean object without a prototype”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A clean object, an object with no prototype at all, is created with `Object.create(null)`: for it `Object.getPrototypeOf(obj) === null`, and it inherits no built-in method such as `toString` or `hasOwnProperty`.** That makes it an ideal data store, a dictionary where no key can collide with a built-in name, `__proto__` included. ```javascript const dict = Object.create(null); dict.toString = 'value'; // just an ordinary key console.log(Object.getPrototypeOf(dict)); // null ``` **Key point:** `Object.create(null)` gives you an object with no prototype chain, and the price is that it has no built-in methods.Shown above the full answer for quick recall.Answer (EN)Image**A clean object (also called an object dictionary) is an object with no prototype, that is, without `Object.prototype` and all of its built-in methods such as `toString` or `hasOwnProperty`.** Such an object is a perfect fit for pure data stores, dictionaries and maps, where you want to be sure that no built-in property collides with your keys. ## Theory ### TL;DR - A clean object is created with `Object.create(null)`. - For it `Object.getPrototypeOf(obj)` is `null`, there is no prototype chain at all. - It has no `toString`, no `hasOwnProperty` and no special `__proto__` behaviour. - So keys like `toString` or `__proto__` become ordinary keys and break nothing. - Check for a property with `Object.prototype.hasOwnProperty.call(obj, key)` or `Object.hasOwn(obj, key)`. - The modern alternative for dictionaries is `Map`. ### Quick example The simplest and correct way: ```javascript const obj = Object.create(null); ``` This creates an object without a prototype: `obj.__proto__` is `undefined` and `Object.getPrototypeOf(obj)` is `null`. Let us check: ```javascript const obj = Object.create(null); console.log(Object.getPrototypeOf(obj)); // null console.log('__proto__' in obj); // false console.log(typeof obj.toString); // "undefined" ``` Such an object has no inheritance chain: it does not even inherit from `Object.prototype`. ### Why this is useful Ordinary objects inherit a pile of built-in methods: ```javascript const normal = {}; console.log(Object.getPrototypeOf(normal) === Object.prototype); // true // These methods are available console.log(normal.hasOwnProperty); // [Function] console.log(normal.toString); // [Function] ``` That can be dangerous when your keys overlap with those names: ```javascript const map = {}; map.toString = 'value'; // may break code that later calls map.toString() ``` A clean object removes the problem: ```javascript const map = Object.create(null); map.toString = 'value'; // just a key console.log(map.toString); // "value" ``` ### Example use: dictionaries and maps ```javascript const dict = Object.create(null); dict.apple = 1; dict.banana = 2; dict['__proto__'] = 3; // safe, it does not affect the prototype console.log(dict.apple); // 1 console.log(dict['__proto__']); // 3 ``` On ordinary objects `__proto__` has special behaviour (it is an accessor on `Object.prototype`), while here it is a plain property. That is why clean objects are often used for caches and for parsing data that came from outside: they are naturally protected against prototype pollution. ### The drawback: no built-in methods ```javascript const obj = Object.create(null); obj.name = 'Alice'; console.log(obj.hasOwnProperty('name')); // TypeError: obj.hasOwnProperty is not a function ``` If you need to check whether a property exists, use the safe form: ```javascript console.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // true console.log(Object.hasOwn(obj, 'name')); // true, the modern form ``` The same applies to `toString()`: such an object cannot simply be concatenated with a string, and in some environments `console.log` prints it as `[Object: null prototype]`. ### The alternative: use `Map` The modern way to store dictionaries: ```javascript const map = new Map(); map.set('apple', 1); map.set('__proto__', 2); console.log(map.get('__proto__')); // 2 ``` `Map` solves the same problem, but it accepts keys of any type, objects included, preserves insertion order and exposes a `size` property. ### Summary | Approach | Prototype | Access to built-in methods | Suitable for dictionaries | | --- | --- | --- | --- | | `{}` | `Object.prototype` | yes (`toString`, `hasOwnProperty`) | risky | | `Object.create(null)` | `null` | no | yes | | `new Map()` | not a plain object | the `set`, `get`, `has` methods | yes, the modern option | > To create a clean object without `Object.prototype`, use `const obj = Object.create(null)`: it inherits nothing and is a perfect fit for safe dictionaries. ### Common mistakes - **Calling `obj.hasOwnProperty(key)` on a clean object.** You get a `TypeError`, because the method simply is not there. Use `Object.hasOwn(obj, key)`. - **Confusing `Object.create(null)` with `{}`.** The latter inherits from `Object.prototype` with everything that implies. - **Passing a clean object into code that expects a normal one.** A library that internally calls `value.toString()` will throw. - **Assuming `JSON.stringify` does not work.** It works fine, the trouble is with implicit string coercion. - **Using a clean object where `Map` fits better.** If the keys are not strings, or you need size and ordering, reach for `Map`. - **Forgetting that an object from `JSON.parse` is an ordinary one.** Parsing external JSON yields an object with a prototype, so validate the `__proto__` key before merging.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.