Object.create(proto) makes an object whose [[Prototype]] is proto, and proto may be null. Object.create throws a TypeError if proto is neither an object nor null. With null, the object's chain is empty: it has no inherited properties at all.
Use it when an object is a dictionary keyed by data you don't control (words, usernames, header names, query keys):
- On a normal object,
'toString' in tableandtable['constructor']are truthy even though nobody stored them, so lookups, counters and "seen before" checks give wrong answers. - The
__proto__key is special on a normal object:table['__proto__'] = valueruns the inherited accessor and changes the prototype instead of storing a key. WithoutObject.prototype,__proto__is an ordinary key.
The platform does the same for keyed data: Object.groupBy returns a null-prototype object, and so does Node's querystring.parse.
The costs:
- No
toString/valueOf:`${dict}`anddict + ''throwTypeError. - No
hasOwnProperty: useObject.hasOwn(dict, key)orkey in dict(safe, because nothing is inherited). dict instanceof Objectisfalse, and some libraries and assertion helpers assumeObject.prototypeexists.{ ...dict }andObject.assign({}, dict)return ordinary objects, so copying loses the property.
{ __proto__: null } in an object literal is equivalent and more readable, because the literal form sets [[Prototype]] directly. For a real dictionary, prefer Map: any key type, insertion order, size, and no prototype pitfalls at all. Reach for a null-prototype object when you need an object shape, like JSON output or property syntax.