Introduction
Prototypal inheritance (eng. prototypal inheritance) is a type of inheritance where an object inherits properties directly from another object (not from a template, ie class). There are two basic mechanisms that enable prototypical inheritance:
- Concatenative inheritance
This process is based on directly copying the properties of one or more objects to a new object. It should be noted that in order to copy a property, it is necessary that the property’s enumerable descriptor be set to true. This mechanism is also accepted with the ES2015 standard, with the help of the “Object.assign()” method.
123456var o1 = { a: 1, b: 1, c: 1 };var o2 = { b: 2, c: 2 };var o3 = { c: 3 };var velikiObjekat = Object.assign({}, o1, o2, o3);console.log(velikiObjekat); // { a: 1, b: 2, c: 3 } - Prototype delegation
This process is based on the principle that properties and methods are inherited through a “chain of related prototype objects” (eng. “prototype chain”).
NOTE:
In the framework of the ES2015 standard, a syntax for creating objects via classes is presented, however, this is only an aesthetic change, because in the background, all work related to inheritance is performed according to the previously mentioned mechanism “prototype delegation”.
Prototypical delegation
Definition

Prototypal delegation is the most important object inheritance mechanism in JavaScript. It is based on the principle that properties and methods are inherited through a “chain of connected prototype objects” (eng. “prototype chain”).
The Object() function is the “mother” of all objects, which through its “Object.prototype” object passes some basic properties and methods to all newly generated objects. Read more about this property of the constructor function Object() in the article Object() & Object.prototype
Each new object also has its own “prototype” object which is empty at first, but is connected via a “inheritance chain” to the parent object, its parent object and so on until Object.Prototype of the object. An inheritance chain is actually a set of related prototype objects that ends with Object.prototype.
In order for an object to be able to pass a method to its successor, it is necessary to define the method in its prototype object, because that way it is accessible to other objects that will be created based on it.
|
1 2 3 |
someObject.prototype.metodaZaNasledjivanje = function(){ // the body of the method to inherit } |
EXPLANATION:
When the JavaScript engine looks for a method, it first checks if we have defined it within our own prototype objects. If it does not find it there, then it looks for it in the prototype object of the parent. But if it does not find it there, it will search further along the chain of interconnected prototype objects until it reaches the last one in the chain “Objec.prototype”. If it doesn’t find it in it either, it throws an error.
Why use prototypical delegation?
The reason for using prototypical delegation as the main method of inheritance is good resource optimization, and this is best explained by comparing it with a non-optimizing mechanism. First, we’ll generate objects based on the constructor f only, using the new keyword. Objects generated in this way get a copy of the properties and methods found in theconstructor function at the moment of generation.
|
1 2 3 4 5 6 7 8 9 10 |
function Auto(marka, model, godinaProizvodnje) { this.motor = "diesel"; this.marka = marka; this.model = model; this.godProizvodnje = godinaProizvodnje; this.prikaziPoruku = function(){ console.log("Auto je: " + this.marka +" " + this.model + " proizveden " + this.godProizvodnje + "year") }; } var mojAuto = new Auto("Citroen", "C5", 2012); |
The newly generated object (myCar) has received a copy of all properties. Therefore, we should pay attention to the fact that if
|
1 2 |
Auto.motor = "Benzinac"; // let's change the value property of the constructor function mojAuto.motor; // Returns: "diesel" (no effect of changing the constructor property on the instantiated object) |
The bad side of this approach comes to light when a large number of new objects are instantiated based on this constructor function. The reason for this is the fact that when new objects are instantiated in each object, methods are also instantiated, so this approach unnecessarily consumes resources for instantiating the same method in each object.
To obtain more optimized code, the mechanism “constructor function + prototype inheritance” is recommended. In this mechanism, the methods needed by all new objects are defined in the “prototype object“. Such methods placed in the prototype object are instantiated only once within that parent object, while they are delegated to other objects (generated on the basis of the parent) along the chain of inheritance. The properties are specific for each object, so we define them in the constructor function, because that way each new object gets its own copy with specific values.
|
1 2 3 4 5 6 7 8 9 10 |
function Auto(marka, model, godinaProizvodnje) { this.marka = marka; this.model = model; this.godProizvodnje = godinaProizvodnje; } Auto.prototype.prikaziPoruku = function(){ console.log("Auto je: " + this.marka +" " + this.model + " proizveden " + this.godProizvodnje + "year") }; var mojAuto = new Auto("Citroen", "C5", 2012); mojAuto.prikaziPoruku(); // Returns: "Car is: Citroen C5 manufactured in 2012" |
After generating a new object (“myCar”), the showMessage() method is available to it, which is instantiated only in the parent prototype object.
NOTE:
Inheritance via prototype objects is a “living thing”! If a property in the prototype object is subsequently changed, it will affect all generated objects that inherit that property along the inheritance chain.
Prototypic inheritance by example
The working principle of inheriting objects by delegating properties will be best explained through examples.
Basic object:
We’ll start with a simple constructor function Initial() and its object prototype, and generate new objects using the new() keyword:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function Pocetni(ulaz1, ulaz2) { this.svojstvoPrvo = ulaz1; this.svojstvoDrugo = ulaz2; } Pocetni.prototype.metodPrvi = function() { console.log(this.svojstvoPrvo) }; Pocetni.prototype.metodDrugi = function() { console.log(this.svojstvoDrugo) }; // ************** NEW FACILITY ********************** var pocetni1 = new Pocetni("value1", "value2"); pocetni1.metodPrvi(); // Returns "value1" pocetni1.metodDrugi(); // Returns "value2" |
A constructor function and its prototype object in JavaScript are the closest we can get to the concept of a class from other programming languages. The newly generated object, during the very act of creating the object, copied all properties from the constructor function (Initial()), and linked its prototype object with the parent object. It should be emphasized that our new object (“initial1”), like any object generated with the “new” keyword, does not have its own constructor function (there is no “Initial1()” function), so its .constructor property points to the Initial() constructor function.

Extended object:
The next part describes the procedure for creating a new object that extends the Start() function:
a) Creating a new constructor function and linking it to the Initial()
properties
Creating a modified “template object” starts with defining a new constructor function:
|
1 2 3 |
function ModifikovaniPocetni(ulaz3) { this.svojstvoTrece = ulaz3; } |
To inherit properties from another constructor function, we use the call() method. The call() method allows us to redefine the meaning of the “this” keyword. It’s up to usit is necessary that “this” written in the “Initial()” constructor function points to newly created objects created using the ModifiedInitial() function. Therefore, for the first parameter of the method (responsible for redefining “this”), we write “this”, because with this we define that the meaning of the word “this” indicates “this” (and that is by using the keyword new is actually a newly generated object). Through the other parameters of the call() method, we pass two parameters necessary for the First property and the Second property.
|
1 2 3 4 |
function ModifikovaniPocetni(ulaz1, ulaz2, ulaz3) { Pocetni.call(this, ulaz1, ulaz2); this.svojstvoTrece = ulaz3; } |
b) Connecting prototype objects with the chain of inheritance
Depending on how we want to assign methods to our “ModifiedInitial.prototype” object, associating the prototype object can be done with:
-
new()
Since every newly generated object is “hooked” into the inheritance chain, by assigning the newly generated object to our prototype object we give our prototype object access to the “inheritance chain”.
1ModifikovaniPocetni.prototype = new Pocetni()However, this method is not recommended because by using it, we unnecessarily insert properties from the constructor function (propertyFirst, propertySecond) into the inheritance chain.
-
Object.create()
This approach is recommended, because in addition to creating a new object, the “Object.create()” method also directly connects two prototype objects (the prototype object of the newly created object and the parent prototype). By this binding to the parent prototype, our new object is “hooked” into the entire inheritance chain, so all methods from it are available to it.
1ModifikovaniPocetni.prototype = Object.create(Pocetni.prototype);However, since our “ModifiedInitial()” constructor function was not used in this connection of prototype objects, the JavaScript engine does not recognize it, so it will search “deeper” along the inheritance chain, where it is found as the “Initial()” function. So our new object’s .constructor method currently points to the wrong “Initial()” object. This is not good, so we need to change it:
1ModifikovaniPocetni.prototype.constructor = ModifikovaniPocetni
c) Adding new functionalities
After extending our new object with the properties and methods of the “parent” object, we can “enrich” our new object with new functionalities:
|
1 2 3 |
ModifikovaniPocetni.prototype.metodTreci = function() { console.log(this.svojstvoTrece) }; |
We can even change the extended method, by defining in our object a method with the same name that will “shadow” (eng. shadowing) the inherited method.
|
1 2 3 |
ModifikovaniPocetni.prototype.metodDrugi = function() { console.log("Obscured second method" ) }; |
Thus, all objects created based on this modification have the following functionalities:
|
1 2 3 4 |
var modifikovaniPocetni1 = new ModifikovaniPocetni("entry 1", "entry2", "entry3" ); modifikovaniPocetni1.metodPrvi(); // Returns "entry1" modifikovaniPocetni1.metodDrugi(); // Returns "Another method hidden" modifikovaniPocetni1.metodTreci(); // Returns "entry3" |

Unified code from example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// ********************************* STARTING FACILITY ********************************** function Pocetni(ulaz1, ulaz2) { this.svojstvoPrvo = ulaz1; this.svojstvoDrugo = ulaz2; } Pocetni.prototype.metodPrvi = function() { console.log(this.svojstvoPrvo) }; Pocetni.prototype.metodDrugi = function() { console.log(this.svojstvoDrugo) }; //************** Generisani pocetni objekti *********************** var pocetni1 = new Pocetni("value1", "value2"); pocetni1.metodPrvi(); // Returns "value1" pocetni1.metodDrugi(); // Returns "value2" // ********************************** EXTENDED FACILITY ********************************** function ModifikovaniPocetni(ulaz1, ulaz2, ulaz3) { Pocetni.call(this, ulaz1, ulaz2); this.svojstvoTrece = ulaz3; } ModifikovaniPocetni.prototype = Object.create(Pocetni.prototype); ModifikovaniPocetni.prototype.constructor = ModifikovaniPocetni; ModifikovaniPocetni.prototype.metodTreci = function() { console.log(this.svojstvoTrece) }; ModifikovaniPocetni.prototype.metodDrugi = function() { console.log("Obscured second method"); }; //********** Generisani ekstendovani objekti ******************* var modifikovaniPocetni1 = new ModifikovaniPocetni("entry 1", "entry2", "entry3" ); modifikovaniPocetni1.metodPrvi(); // Returns "entry1" modifikovaniPocetni1.metodDrugi(); // Returns "Another method hidden" modifikovaniPocetni1.metodTreci(); // Returns "entry3" |

