Implementing Prototypal Inheritance in JavaScript

Back in 2006, Douglas Crockford introduced a significant pattern in his article "Prototypal Inheritance in JavaScript." This approach enables object inheritance without the rigid structure of formal constructor functions. The primary premise is that objects can share data via their prototypes even when custom type definitinos are absent.

Crockford outlined a utility function to achieve this goal:

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

This object() helper instantiates a temporary constructor. It sets the input object as the prototype for this temporary class and returns an instance. Effectively, calling object() produces a shallow copy of the provided object. Observe how this behaves in practiec:

const templateUser = { 
  name: "John", 
  hobbies: ["Chess", "Reading"] 
}; 

const userCopyOne = object(templateUser); 
userCopyOne.name = "Mark"; 
userCopyOne.hobbies.push("Coding"); 

const userCopyTwo = object(templateUser); 
userCopyTwo.name = "Sarah"; 
userCopyTwo.hobbies.push("Gaming"); 

console.log(templateUser.hobbies); 
// ["Chess", "Reading", "Coding", "Gaming"]

This technique is ideal when you possess an existing object and wish to construct a derivative. You pass the base object to object() to get a clone, which you then modify. Since the new instance's prototype links to the original, it inherits both primitive and reference attributes. This implies that mutable reference types, like arrays, are shared among all children of the base object.

With the advent of ECMAScript 5, this concept was formalized using the built-in Object.create() method. This function takes two parameters: an object to serve as the prototype for the new entity, and an optional descriptor object for defining additional properties.

const templateUser = { 
  name: "John", 
  hobbies: ["Chess", "Reading"] 
}; 

const userCopyOne = Object.create(templateUser); 
userCopyOne.name = "Mark"; 
userCopyOne.hobbies.push("Coding"); 

const userCopyTwo = Object.create(templateUser); 
userCopyTwo.name = "Sarah"; 
userCopyTwo.hobbies.push("Gaming"); 

console.log(templateUser.hobbies); 
// ["Chess", "Reading", "Coding", "Gaming"]

The second argument of Object.create() mirrors the interface of Object.defineProperties(). Any attributes added in this step utilize their own descriptors, causing them to override matching properties on the prototype chain. For instance:

const templateUser = { 
  name: "John", 
  hobbies: ["Chess", "Reading"] 
}; 

const userCopyOne = Object.create(templateUser, { 
  name: { 
    value: "Mark" 
  } 
}); 

console.log(userCopyOne.name); 
// "Mark"

Prototypal inheritance offers a flexible alternative for cases where explicit constructors are unnecessary but data sharing between objects is required. Developers should note, however, that any properties holding reference values will retain shared state across related objects, consistent with standard prototype mechanics.

Tags: javascript prototypal-inheritance ecmascript-5 object-create

Posted on Fri, 23 Oct 2026 16:22:49 +0000 by Juan Dela Cruz