How Object.create Establishes Prototypes in JS
This article explains how JavaScript’s Object.create()
method creates and manages prototype links between objects. You will
learn the mechanics behind the hidden [[Prototype]]
reference, how the prototype chain performs property lookups, how to
define additional properties using property descriptors, and why this
method provides a direct approach to object inheritance compared to
standard constructor functions.
The Fundamental Mechanism
In JavaScript, objects inherit properties and methods through a
mechanism called the prototype chain. Every JavaScript object has an
internal hidden link, known in ECMAScript specifications as
[[Prototype]] (accessible in most runtime environments via
__proto__ or Object.getPrototypeOf()).
When you invoke Object.create(proto), JavaScript creates
a completely new, empty object and sets its internal
[[Prototype]] reference directly to the proto
object passed in the first argument.
const parent = {
greet() {
return "Hello from parent";
}
};
// Create a new object with 'parent' as its prototype
const child = Object.create(parent);
console.log(child.greet()); // "Hello from parent"
console.log(Object.getPrototypeOf(child) === parent); // trueProperty Delegation and Lookup
Object.create() does not copy properties from the source
object to the new object. Instead, it relies on delegation:
- When accessing a property on
child(e.g.,child.greet), the JavaScript engine checks if the property exists directly onchild(as an “own property”). - If it is not found on
child, the engine traverses the internal[[Prototype]]link toparent. - If found on
parent, that value or method is executed. - If not found, the engine continues up the chain to
Object.prototypeand eventually returnsundefinedif the root of the chain (null) is reached.
Defining Properties with Descriptors
Object.create() accepts an optional second argument that
allows you to define own properties on the newly created object using
property descriptors.
const personProto = {
describe() {
return `Name: ${this.name}`;
}
};
const user = Object.create(personProto, {
name: {
value: "Alex",
writable: true,
enumerable: true,
configurable: true
}
});
console.log(user.describe()); // "Name: Alex"
console.log(user.hasOwnProperty("name")); // trueCreating Objects Without a Prototype
A distinctive capability of Object.create() is its
ability to create a “pure dictionary” object with no prototype link
whatsoever by passing null.
const bareObject = Object.create(null);
console.log(Object.getPrototypeOf(bareObject)); // null
console.log(bareObject.toString); // undefined (does not inherit from Object.prototype)This prevents prototype pollution and ensures that default methods
like toString or hasOwnProperty do not collide
with user-defined keys.
Object.create()
vs Constructor Functions
Traditional inheritance using constructor functions relies on the
new operator and the constructor’s .prototype
property:
function Parent() {}
Parent.prototype.greet = function() { return "Hi"; };
const child = new Parent();Object.create() bypasses the constructor function
entirely, allowing direct object-to-object linkage. It cleanly separates
object creation from initialization, establishing explicit inheritance
with minimal overhead.