Search Knowledge

© 2026 LIBREUNI PROJECT

Modern JavaScript & Ecosystem / Object-Oriented JavaScript

The Prototype Chain and Inheritance

Prototypal vs. Classical Inheritance

Unlike languages like Java or C++, which utilize class-based inheritance, JavaScript is a prototype-based language. While ES6 introduced the class keyword, it is primarily “syntactic sugar” over JavaScript’s existing prototypal inheritance mechanism. In classical inheritance, classes are blueprints and objects are instances. In prototypal inheritance, objects inherit directly from other objects.

Every object in JavaScript has an internal property called [[Prototype]]. This is a link to another object. When you attempt to access a property on an object, JavaScript first looks at the object itself. If the property is not found, it follows the [[Prototype]] link to the next object and searches there. This continues until the property is found or the end of the chain (usually Object.prototype, which points to null) is reached.

The [[Prototype]] of an object can be accessed via Object.getPrototypeOf(obj) or the deprecated __proto__ property.

Constructors and the prototype Property

When a function is used with the new keyword, it acts as a constructor.

  1. A new empty object is created.
  2. The new object’s [[Prototype]] is set to the function’s prototype property.
  3. The constructor function is executed with this bound to the new object.
  4. The object is returned (unless the constructor returns a different object).

It is crucial to distinguish between an object’s prototype ([[Prototype]]) and a function’s prototype property. The prototype property is only used when the function is used as a constructor to set the [[Prototype]] of the new instance.

Code
skinparam monochrome true

object "myArray (Instance)" as instance {
length = 2
}

object "Array.prototype" as arrayProto {
push()
pop()
slice()
}

object "Object.prototype" as objProto {
toString()
hasOwnProperty()
}

instance ..> arrayProto : [[Prototype]]
arrayProto ..> objProto : [[Prototype]]
objProto ..> null : [[Prototype]]
myArray (Instance)length = 2Array.prototypepush()pop()slice()Object.prototypetoString()hasOwnProperty()nullPrototypePrototypePrototype

Method Delegation

The primary benefit of the prototype chain is reference-based delegation. Instead of every object instance having its own copy of a method (which consumes memory), methods are defined on the prototype. All instances share the same function implementation.

javascript
1function Animal(name) {
2 this.name = name;
3}
4 
5Animal.prototype.speak = function() {
6 return this.name + " makes a noise.";
7};
8 
9const dog = new Animal("Rex");
10console.log(dog.speak()); // "Rex makes a noise."
11console.log(dog.hasOwnProperty('speak')); // false (it's on the prototype)

Shadowing Properties

If you define a property on an instance with the same name as a property on its prototype, the instance property “shadows” the prototype property. The lookup mechanism finds the instance property first and stops searching.

The Object.create() Method

Object.create(proto) provides a cleaner way to create an object with a specific prototype without needing a constructor function or the new keyword.

javascript
1const machine = {
2 type: "universal",
3 compute: function() { return "Computing..."; }
4};
5 
6const turing = Object.create(machine);
7turing.id = "Alan";
8 
9console.log(turing.compute()); // "Computing..."
10console.log(Object.getPrototypeOf(turing) === machine); // true

Performance Considerations

Traversal of the prototype chain can be expensive if the chain is long. Checking for a property using in scans the entire chain, whereas hasOwnProperty() only checks the instance itself. Modern engines like V8 optimize property access using “Hidden Classes”, but deeply nested prototype structures should still be used with caution.