DEV Community

Cover image for Prototypes in JavaScript.
Tanmay Agrawal
Tanmay Agrawal

Posted on

Prototypes in JavaScript.

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
Enter fullscreen mode Exit fullscreen mode
  • 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 the Object.getPrototypeOf() method).

const myObject = {}; // An empty object
console.log(Object.getPrototypeOf(myObject)); // The prototype of myObject

Enter fullscreen mode Exit fullscreen mode
  • 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)
Enter fullscreen mode Exit fullscreen mode
  • 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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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())

Prototype Chaining

'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]
Enter fullscreen mode Exit fullscreen mode

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)