JavaScript Object Prototypes

Ashish ShahAshish Shah
5 min read

Hey! This is Ashish Shah, writing this Article on 19 Fab 2025, explaining the prototype property of JavaScript and its superpower. I’m listening to the song Kill Me Slowly By Sickick

Have you ever wondered why most things in JavaScript are either objects or behave like objects? or why are you able to access .toString() method on any object without defining it at the time of object creation? This is because JavaScript has a property known as prototype. Let’s dive deep into what a prototype is and how it works internally to make JavaScript seem almost entirely object-oriented.

In JavaScript, Object class or Object type is the base class for almost all objects.
It is the fundamental part of the language itself, that provides some properties and methods to all objects either directly or via inheritance.

So, the Object class has a property known as prototype, and we can access it using . operator. If you console Object.prototype you’ll get something like this in the image:

So, when you create any function, class or data type like below, the JavaScript engine injects all the above properties and methods of base class into that data type.
e.g: class

class Person{
    constructor(fname, lname,) {
        this.firstname = fname;
        this.lastname = lname;
    }
    getFullName() {
        if (this.lastname !== undefined) 
            return `${this.firstname} ${this.lastname}`
        return this.firstname;
    }
}
const objectOne = new Person("Ashish", "Shah");

and If we do console Person.prototype we’ll get something like this:

So, what is happening under the hood is: that JavaScript is creating a property prototype to class Person, and injecting all the methods that are defined inside the class along with base Object class’s properties and method via Person.prototype = Object.prototype. That’s why at the start we’re able to see our user-defined method and then the base Object class methods. JavaScript does the same to all types of classes either predefined (String, Array, Number, Boolean, Function, Date etc) or user-defined as above (That’s the reason almost everything in JS seems an object because in some way they all have Object class’s methods and properties). It creates a prototype property and injects it into all base class methods or parent class methods into the object’s prototype property.

So even on a string, we’re able to call a method .toUpperCase() like the below without defining it and also on the object we’re able to call .toString() method.

let name = "Ashish shah"
name.toUpperCase();
//Output: ASHISH SHAH
let one = {
    fname: "Ashish",
    lname: "Shah"
}
one.toString()
// output: [object Object]

So what prototype is?

prototype is a way of accessing the properties and methods of other objects (as we were accessing methods of the base Object class on string class above). But the superpower of prototype comes here: Let’s take the example of below code snippet

const objOne = {
    fname: "Ashish",
    lname: "Shah",
    getFullName: function () {
        if (this.lname !== undefined) return `${this.fname} ${this.lname}`
        return this.fname;
    }
}

const objTwo = {
    fname: "Abhay",
    lname: "Sharma",
}

console.log(objOne.getFullName())
console.log(objTwo.getFullName())

Can you guess the output for both the console.log() ? (try on). For the first console.log() the output will be Ashish Shah and for the second console.log() we’ll get an error saying: Uncaught TypeError: objTwo.getFullName is not a function. Why is that so? Simply because we don’t have a method named getFullName in the objTwo object, right? Absolutely right. But what if we can make a way so that we can access the getFullName method on objTwo as well? (I’m not gonna write again the getFullName method in objTwo because it will violet DRY concept in programming).

So when you run this line: console.log(objTwo.getFullName()), the interpreter’s flow will go like the below image:

First will check into object definition methods and if it doesn’t find then goes into .__proto__ property’s methods.

objTwo.__proto__ 
/* .prototype this is the way of accessing prototype values on class like
   String, Array, Date, Person but .__proto__ is the way of accesing 
   prototype on the object/instance of classes.
*/

and internally JavaScript injects all the properties and methods of its parent class. Here JavaScript did something like this:

objTwo.__proto__ = Object.prototype

and here comes the superpower of the prototype property. If JS engine doing like this objTwo.__proto__ = Object.prototype then can’t we modify it and inject the objOne methods and properties into objTwo.__proto__ then we’ll have access to the getFullName method into objTwo as well. Yessssss ofc we can do.

const objTwo = {
    fname: "Abhay",
    lname: "Sharma",
}
objTwo.__proto__ = objOne

Now if you print objTwo, you’ll able to see the getFullName method inside of objTwo.__proto__

and the third box’s methods are coming from objOne.__proto__, and the second box methods are coming from the objOne object’s definition (or objTwo.__proto__) and the first box’s methods are coming from objTwo object’s definition and this goes on until the interpreter reaches null and this is known as prototype chaining.

Prototype chaining:

Keep on checking the methods or properties of the objects by JS interpreter into the object’s prototype until it reaches to null value, is known as prototype chaining.
For the above image, the JS interpreter will go like this:

objTwo -> objTwo.__proto__ -> objTwo.__proto__.__proto__ -> .... until
objTwo.__proto__.__proto__....__proto__ = null

Inheritance:

Inheriting properties and methods from different objects either directly(using extends keyword) or indirectly (via prototype chaining) is known as inheritance.

// direct inheritance:
class A{
    funInsideA() {
        console.log("Hello from A class.")
    }
}

class B extends A{
    funInsideB() {
        console.log("Hello from B class.")
    }
}
console.log(B.prototype)
// Now class B will also have funInsideA method


// indirectly: via prototype chaining as we were doing earlier
class A{
    funInsideA() {
        console.log("Hello from A class.")
    }
}

class B{
    funInsideB() {
        console.log("Hello from B class.")
    }
}
B.prototype = A.prototype

Prototype Inheritance:

Inheriting properties and methods via prototype chaining is known as prototype inheritance. below, you can go as nested as you want.

class A{
    funInsideA() {
        console.log("Hello from A class.")
    }
}

class B{
    funInsideB() {
        console.log("Hello from B class.")
    }
}
B.prototype = A.prototype

Now, can you get the job done of extends keyword without using it? if yes then return something or else read from different sources and come again on this article, you’ll get to know how easy I’ve explained without video :)

Thanks for the reading guys, keep reading and keep writing articles.

23
Subscribe to my newsletter

Read articles from Ashish Shah directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ashish Shah
Ashish Shah