JavaScript Object Prototypes


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.
Subscribe to my newsletter
Read articles from Ashish Shah directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
