Front Runner Front End Web Development Blog

What is a JavaScript Prototype?

A prototype, in terms of JavaScript, is inbuilt functionality that has a unique feature for object inheritance referred to as the prototype

| March 16, 2025 | 7 min read

JavaScript is a dynamically typed language and employs a unique mechanism for object inheritance: prototypes. Unlike classical inheritance found in languages like Java or C++, JavaScript utilises prototype-based inheritance, a powerful and flexible approach that can be both elegant and initially confusing. We will explore and unravel the intricacies of JavaScript prototypes, exploring their functionality, advantages and potential disadvantages.

Understanding the Basics – Objects & Properties

Before diving into prototypes, it’s crucial to understand the fundamental building blocks of JavaScript: objects. Objects are collections of key-value pairs, where keys are typically strings (or Symbols) and values can be any JavaScript data type – numbers, strings, booleans, other objects, or even functions and these key-value pairs are called properties.

const myObject = {
  name: "Alice",
  age: 30,
  city: "New York",
  greet: function() {
    console.log(`Hello, my name is ${this.name}!`);
  }
};

console.log(myObject.name); // Accessing a property
myObject.greet(); // Calling a method (function property)

Prototype – The Foundation of Inheritance

Every object in JavaScript has a hidden property called [[Prototype]] (often referred to as __proto__ in older implementations, though directly accessing it is discouraged). This property points to another object which serves as the prototype for the original object. Think of the prototype as a blueprint or template from which the object inherits properties and methods.

When you try to access a property of an object, JavaScript first checks if the object itself has that property. If it does, the value is returned. However, if the property isn’t found directly on the object, JavaScript’s engine follows the [[Prototype]] link to the prototype object. It then checks if the prototype object has the desired property. This process continues up the prototype chain until either the property is found or the end of the chain (which is null) is reached.

Creating Objects & Prototypes

There are several ways to create objects in JavaScript, each influencing how prototypes are assigned:

  1. Object Literals: When you create an object using object literal notation (as shown in the myObject example above), its prototype is, by default, Object.prototype, the base prototype for all objects in JavaScript.
  2. new Keyword and Constructor Functions: Constructor functions are functions designed to create and initialise objects. When you use the ‘new’ keyword with a constructor function, a new object is created, and the constructor function is called with this bound to the new object. Crucially, the new object’s prototype is set to the prototype property of the constructor function.
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hi, I'm ${this.name}.`);
};

const john = new Person("John", 25);
john.greet(); // Accessing a method from the prototype

In this example, Person.prototype is the prototype for all objects created using the Person constructor. john inherits the greet method from Person.prototype.

  1. The Object.create(): This  system allows you to  produce a new object with a specified prototype. This offers further control over prototype inheritance.
const parent = {
  name: "Jane",
  sayHi: function() { console.log("Hi!"); }
};

const child = Object.create(parent);
child.name = "David"; // Overriding the parent's name property
child.sayHi(); // Inheriting the sayHi method
console.log(child.name); // Accessing the overridden property

Here, child’s prototype is parent. child inherits sayHi but overrides the name property.

The Prototype Chain – A Journey Upward

The [[Prototype]] link forms a chain, known as the prototype chain. When you access a property, JavaScript traverses this chain until it finds the property or reaches the end (where the prototype is null). This is how inheritance works in JavaScript. Objects inherit properties and methods from their prototypes, and those prototypes can inherit from other prototypes creating a hierarchy.

Benefits of Prototype-Based Inheritance

  • Efficiency: Methods are typically defined on prototypes, not directly on each object instance. This saves memory because multiple objects can share the same method implementation.
  • Flexibility: Prototype inheritance is dynamic. You can modify prototypes at runtime, and those changes will be reflected in all objects that inherit from that prototype.
  • Code Reusability: Prototypes promote code reuse by allowing you to define shared functionality in one place and have multiple objects inherit it.

Potential JavaScript Prototype Pitfalls

  • Shadowing: If an object has a property with the same name as a property on its prototype, the object’s own property “shadows” the prototype’s property. This can lead to unexpected behaviour if web developers are not aware of the shadowing.
  • Modifying Prototypes: While modifying prototypes is powerful, it can also be dangerous. If multiple objects share a prototype, changing the prototype can affect all of those objects, potentially leading to unintended consequences.

Simulating Classical Inheritance (Not Recommended)

While JavaScript’s prototype-based inheritance is different from classical inheritance, it’s possible to simulate some aspects of classical inheritance using prototypes. However, this is often discouraged as it can add complexity and obscure the true nature of JavaScript’s prototype system. It’s generally better to embrace the prototype-based approach head on.

Modern JavaScript & class Syntax

ECMAScript 2015 (ES6) introduced the class syntax, which provides a more familiar way to define objects and their prototypes. Under the hood, the class syntax still uses prototypes; it’s just syntactic sugar that makes it look more like classical inheritance.

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  bark() {
    console.log("Woof!");
  }
}

const myDog = new Dog("Buddy");
myDog.speak(); // Inherited from Animal
myDog.bark(); // Defined on Dog

The extends keyword in the class syntax establishes the prototype relationship. Dog’s prototype is Animal.prototype, allowing myDog to inherit the speak method.

Conclusion

JavaScript prototypes are a fundamental and powerful feature of the language. Understanding how prototypes work is essential for mastering JavaScript’s object model and effectively utilizing inheritance.

While initially confusing, the flexibility and efficiency of prototype-based inheritance make it a valuable tool for building complex and maintainable JavaScript applications. By embracing the prototype chain and understanding its nuances the full potential of JavaScript’s object-oriented capabilities can be realised.

JavaScript Prototype FAQs

What is the difference between __proto__ & prototype in JavaScript?

__proto__ is a property on an object instance that points to the object’s prototype. It’s a way to access the internal [[Prototype]] property. prototype, on the other hand, is a property of a constructor function. It’s used to define the prototype for objects created using that constructor. In essence, __proto__ links an object to its prototype, while prototype is used to set the prototype for future objects created by a constructor. Directly accessing __proto__ is discouraged; the latest versions of JavaScript use Object.getPrototypeOf() and Object.setPrototypeOf() instead.

How does the prototype chain work?

The prototype chain is a sequence of objects linked together by their [[Prototype]] (or __proto__ in older implementations) properties. When you try to access a property on an object JavaScript first checks if the object has that property. If not, it follows the [[Prototype]] link to the next object in the chain (the object’s prototype) and checks if that object has the property. This process continues up the chain until either the property is found or the end of the chain (which is null) is reached. If the property is not found after traversing the entire chain, undefined is returned. This is how inheritance is implemented in JavaScript.

Can I modify the prototype of an existing object?

Yes, you can modify the prototype of an existing object using Object.setPrototypeOf() or, in older environments, by directly manipulating __proto__ (though, again, this is discouraged). However, modifying prototypes, especially shared prototypes, should be done carefully and with caution. If multiple objects share the same prototype, changing the prototype will affect all of those objects. This can be useful for adding or modifying shared functionality, but it can also lead to unexpected behaviour if not carefully managed. It’s often better to establish the prototype chain correctly when creating the objects initially, rather than modifying it later.

Post Tags
Other articles...