Practice JS Problems

Prototypes and Prototypal Inheritance in JavaScript

Prototypal inheritance is the foundation of the object model in JavaScript. Unlike classical languages (Java, C++), which use classical inheritance, JavaScript implements a dynamic model where objects can inherit properties and methods from each other through prototypes.


What is a Prototype?

A prototype is an object that any other object refers to if it doesn't have the property or method being searched for. Every object in JavaScript can have another object assigned as its prototype. If a property doesn't exist on the object itself during access, the interpreter will "climb up" the prototype chain until it finds the needed property or reaches the null object.

  • childObject: object where property search is performed.
  • parentObject: prototype of childObject.
  • Object.prototype: base prototype from which all objects inherit unless specified otherwise.
  • null: end of chain; if property not found by this point, result will be undefined.

[[Prototype]] Property and proto

In ECMAScript specification, every object has an internal [[Prototype]] property pointing to the prototype. Historically, many environments (e.g., browsers) provide getter/setter __proto__ for accessing it, but this is considered deprecated.

Modern wayObject.getPrototypeOf and Object.setPrototypeOf

const parent = { greet: function() { console.log("Hello!"); } };
const child = {};

// Set parent as child's prototype
Object.setPrototypeOf(child, parent);

// Now child has access to greet() through prototype chain
child.greet(); // "Hello!"

console.log(Object.getPrototypeOf(child) === parent); // true

Object.create

The most convenient way to create an object with needed prototype is using Object.create method

const person = {
  sayName() {
    console.log(`My name is ${this.name}`);
  },
};

const john = Object.create(person);
john.name = "John";
john.sayName(); // My name is John
  • person acts as "parent" (prototype).
  • john — new object whose [[Prototype]] points to person.

Prototype Chain

If we call property/method john.sayName(), and john doesn't have such property, JS will search for this property in person. If person didn't have sayName, interpreter would go to person.__proto__, which is usually Object.prototype, and so on.

Constructor Functions and prototype Property

Before classes appeared in ES6 (ES2015), constructor functions were often used to simulate class behavior.

function User(name) {
  this.name = name;
}

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

const alice = new User("Alice");
const bob = new User("Bob");

alice.sayHi(); // "Hi, I'm Alice"
bob.sayHi();   // "Hi, I'm Bob"
  • User is a constructor function.
  • Property User.prototype is automatically created when function is declared, and it becomes prototype for all objects created with new User(...).
  • alice and bob store reference to instance property name, and methods are taken from User.prototype.

Classes and Prototypal Inheritance

In modern JS versions you can use class, which under the hood still works on prototypes:

class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, I'm ${this.name}`);
  }
}

const tom = new Person("Tom");
tom.greet(); // "Hello, I'm Tom"

// Check prototype
console.log(Object.getPrototypeOf(tom) === Person.prototype); // true
  • Compiler creates constructor function Person and sets Person.prototype property. All methods defined inside class Person {} are written to Person.prototype.

Summary

  • Prototype is a mechanism allowing objects to inherit properties and methods from other objects.
  • In JS every object has hidden [[Prototype]] property, usually referencing another object or null.
  • Prototype chain allows searching for property "bottom-up": from object to its prototype, then to prototype's prototype, and so on.
  • Constructor functions (before ES6) and classes (from ES6) use prototypes "under the hood". Classes are just "syntactic sugar" over constructor functions.
  • Object.create — convenient way to create objects specifying prototype directly. Prototypal inheritance provides powerful, flexible approach to OOP implementation without strict binding to classes.
Practice JS Problems