Object.assign Polyfill
Implement Object.assign from scratch: copy own enumerable properties (including Symbols) from sources onto the target.
JavaScript · Objects · Polyfills — Pratik Rai ·
Implement Object.create using the classic empty-constructor trick to set an object's prototype chain.
Object.create builds a new object with a prototype you choose, optionally defining properties at the same time. It is the most direct way to work with JavaScript's prototypal inheritance without going through constructors or class syntax, and implementing it clarifies what a prototype chain actually is.
Every JavaScript object has an internal link to another object — its prototype. When you read a property that the object does not own, the engine follows that link, and keeps following it, until the property is found or the chain ends at null. That is the entire inheritance mechanism. class is syntax over it; Object.create sets the link directly.
JSfile.javascript1const animal = { 2 describe() { return `${this.name} is a ${this.type}`; }, 3}; 4 5const dog = Object.create(animal); 6dog.name = 'Rex'; 7dog.type = 'dog'; 8 9dog.describe(); // "Rex is a dog" — method found on the prototype 10Object.getPrototypeOf(dog) === animal; // true 11dog.hasOwnProperty('describe'); // false — it is inherited, not owned
dog owns name and type. describe lives on animal and is reached through the chain.
The second argument accepts property descriptors, in the same shape Object.defineProperties uses:
JSfile.javascript1const config = Object.create(null, { 2 apiUrl: { value: 'https://api.example.com', enumerable: true, writable: false }, 3});
Descriptor defaults are the opposite of what people expect: writable, enumerable and configurable all default to false. A property defined without specifying them is read-only and hidden from Object.keys.
Object.create(null) — the null-prototype objectPassing null produces an object with no prototype at all. That means no toString, no hasOwnProperty, no constructor — nothing inherited whatsoever.
This is genuinely useful for dictionaries:
JSfile.javascript1const map = {}; 2map['toString']; // [Function: toString] — inherited, and probably not what you meant 3'constructor' in map; // true 4 5const safe = Object.create(null); 6safe['toString']; // undefined 7'constructor' in safe; // false
Using a plain {} as a lookup table means every key on Object.prototype appears to already exist. That is the root of a class of prototype-pollution bugs, and the reason Object.create(null) is the correct choice for any object keyed by untrusted input.
The trade-off is that such objects lack the usual methods. safe.hasOwnProperty(k) throws. Use Object.hasOwn(safe, k) or Object.prototype.hasOwnProperty.call(safe, k). Map is often the better answer outright — it accepts any key type and has no prototype concerns at all.
Modern engines expose Object.setPrototypeOf, but the classic polyfill predates it and shows the mechanism more plainly:
JSfile.javascript1Object.myCreate = function (proto, propertiesObject) { 2 if (typeof proto !== 'object' && typeof proto !== 'function') { 3 throw new TypeError('Object prototype may only be an Object or null'); 4 } 5 // typeof null === 'object', so null passes the guard above — which is correct. 6 7 function Temp() {} 8 Temp.prototype = proto; 9 const obj = new Temp(); 10 11 if (propertiesObject !== undefined) { 12 Object.defineProperties(obj, propertiesObject); 13 } 14 15 return obj; 16};
The trick is that new sets the new object's prototype to the constructor's prototype property. By pointing a throwaway constructor's prototype at the object you want and immediately calling new, you get an object with the right chain.
This classic version has one limitation it cannot escape: it cannot produce a true null-prototype object. Setting Temp.prototype = null causes new Temp() to fall back to Object.prototype. The genuine null case needs engine support — historically {__proto__: null}, today Object.setPrototypeOf.
Object.create versus the alternativesObject.create(proto) sets the prototype at creation. Fast, and the engine can optimise the object's shape.
Object.setPrototypeOf(obj, proto) changes it afterwards. Correct but slow — mutating an existing object's prototype forces engines to deoptimise every call site that touched it. MDN warns against it explicitly. Use it only when you genuinely cannot set the prototype at creation.
class syntax is what you want for most inheritance. It handles constructor chaining, super, and static members. Object.create is for the cases where you want a prototype link without a constructor — mixins, dictionaries, delegation patterns.
Descriptor defaults are false. Properties created through the second argument are non-writable, non-enumerable and non-configurable unless stated otherwise.
Prototype properties are shared. Mutating an object on the prototype affects every descendant. Assigning dog.name creates an own property that shadows rather than modifies — but dog.settings.theme = 'dark' mutates the shared object.
instanceof walks the chain. Object.create(Array.prototype) instanceof Array is true, even though it is not a real array and has no length behaviour.
Object.create(proto) sets the prototype link directly at creation time.Object.create(null) gives a dictionary with no inherited keys — the right choice for untrusted keys.false.setPrototypeOf, which deoptimises.Goal: Implement Object.myCreate with the empty-constructor trick and support for propertiesObject.
Continue learning with these related challenges
Implement Object.assign from scratch: copy own enumerable properties (including Symbols) from sources onto the target.
JavaScript · Objects · Polyfills — Pratik Rai ·
Group an array into buckets by a key function — now a real language feature as Object.groupBy.
JavaScript · ES6 — Pratik Rai ·
Implement a function that recursively traverses an object, evaluates functions with given arguments, and transforms keys to lowercase. Master recursive object traversal and type checking.
JavaScript · Recursion · Objects — Pratik Rai ·
Implement Object.assign from scratch: copy own enumerable properties (including Symbols) from sources onto the target.
JavaScript · Objects · Polyfills
Pratik Rai ·
Group an array into buckets by a key function — now a real language feature as Object.groupBy.
JavaScript · ES6
Pratik Rai ·
Implement a function that recursively traverses an object, evaluates functions with given arguments, and transforms keys to lowercase. Master recursive object traversal and type checking.
JavaScript · Recursion · Objects
Pratik Rai ·