The prototype chain is a fundamental concept in JavaScript's object-oriented programming model. It plays a crucial role in how objects inherit properties and methods from other objects, allowing for code reuse and the creation of object hierarchies.
to understand the prototype let us explore with a basic example
const car = function(make, model){
this.make = make
this.model = model
console.log(`My car is ${make} ${model}`)
}
const c1 = new car('Tesla', 'Roadster') // My car is Tesla Roadster
console.log(c1) //{make: "Tesla", model: "Roadster"}
car.prototype.speed = function (){
return `My car is ${this.make} ${this.model} and it has a speed of 120km/h`
}
console.log(c1.speed()) //My car is Tesla Roadster and it has a speed of 120km/h)
console.log(car.prototype) // it has a prototype speed function now
console.log(c1.__proto__) // car {speed:f} same as above
console.log(c1.__proto__.__proto__) // Object {} with the key values of all properties
console.log(c1.__proto__.__proto__.__proto__) // null
console.log(car.prototype.__proto__) // Object {}
console.log(car.prototype.__proto__.__proto__) // {} null
console.log(car.prototype === c1.__proto__) // 'true' this means the car prototype is the prototype of its instance c1
console.log(car.prototype.isPrototypeOf(c1))//'true' it is same as writing above code
//Manually setting the properties
car.prototype.drive = 'Front Wheel'
console.log(c1.drive) // Front Wheel
console.log(c1.hasOwnProperty('drive'))//false
console.log(c1.hasOwnProperty('make'))//true
Prototypes and Objects: In JavaScript, almost everything is an object, and each object has a prototype, which is another object. Objects inherit properties (including methods) from their prototypes. You can think of the prototype as a template or a "parent" object.
Object Creation: When you create a new object, either with object literals (
{}
), constructors, or classes, it is initially empty, but it has a hidden reference to its prototype. This prototype reference is accessible via the__proto__
property (though it's typically accessed using theObject.getPrototypeOf()
method).
const myObject = {}; // An empty object
console.log(Object.getPrototypeOf(myObject)); // The prototype of myObject
-
Property Lookup: When you try to access a property or method on an object, JavaScript first looks for that property or method on the object itself. If it doesn't find it, it continues searching in the object's prototype (the prototype of the object). This process continues recursively until the property or method is found or until the prototype chain ends at the
Object.prototype
, which is the ultimate prototype for most objects in JavaScript.
const person = {
firstName: 'John',
lastName: 'Doe',
};
console.log(person.firstName); // Accesses firstName on the person object
console.log(person.toString()); // Searches for toString in the prototype chain (found in Object.prototype)
- Prototype Inheritance: Objects inherit properties and methods from their prototypes. This inheritance allows you to define shared behaviors and properties in prototype objects and reuse them across multiple objects.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
const john = new Person('John', 'Doe');
console.log(john.getFullName()); // Inherited method
In this example, john
is an instance of the Person
constructor, and it inherits the getFullName
method from Person.prototype
.
Prototype Chaining
const Person = function(name, birthYear){
this.name = name,
this.birthYear = birthYear;
}
Person.prototype.calcAge = function(){
console.log(`${this.name} age is ${2023 - this.birthYear}`)
}
const Jonas = new Person('Jonas',1990)
console.log(Jonas.__proto__) // logs Person.prototype
console.log(Person.prototype.__proto__)// returns Object.prototype
console.log(Person.prototype.__proto__.__proto__)// returns null
console.log(Jonas.hasOwnProperty('name'))//true--- this method is inherited from Object prototype
consider above program. here what is happening is.
Jonas is an Object with the __proto__
property which is equal to Person.prototype
and this person prototype is itself an object which is created from the constructor function Person()
Since, every object has its own __proto__
property then this means that person prototype should also has its own i,e, Person.prototype.__proto__
this property is equal to the Object.prototype
Now looking at this Object prototype, it is actually created from yet another constructor function Object()
so basically every object behind the scene is created from Object()
constructor function and therefore inherits Object prototype ({}=== new Object()
)
'The source of this image detail is from the Udemy course
In the statement console.log(Jonas.hasOwnProperty('name'))
What is happening that hasOwnProperty
is not in the Object Jonas so JS lookup in its prototype which is Person.prototype
, Since it is also not defined in there, it will lookup in the Person.prototype.__proto__
and then it reaches the Object.prototype
which actually contains this function hasOwnProperty
Prototype Inheritance on Built-In Objects
let us try this on Arrays
const array = [1, 2, 3, 4, 5, 4, 5, 8, 9, 9];
console.log(array.__proto__) // Array Object prototype,
console.log(array.__proto__.__proto__) // Object prototype
console.dir(array) // this can give the complete prototype chain in console
Array.prototype.unique = function(){
return [...new Set(this)];
}
console.log(array.unique()) //[1, 2, 3, 4, 5, 8, 9]
Here we have tried prototype chain on the array method, once in console we can see all the array methods as its prototype
sofilter
is actually the prototype of the Array object, thats why at mdn document it is written as Array.prototype.filter
Top comments (0)