DEV Community

Cover image for πŸŽ‰πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§ JavaScript Visualized: Prototypal Inheritance
Lydia Hallie
Lydia Hallie

Posted on

πŸŽ‰πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§ JavaScript Visualized: Prototypal Inheritance

Ever wondered why we can use built-in methods such as .length, .split(), .join() on our strings, arrays, or objects? We never explicitly specified them, where do they come from? Now don't say "It's JavaScript lol no one knows, it's magic πŸ§šπŸ»β€β™‚οΈ", it's actually because of something called prototypal inheritance. It's pretty awesome, and you use it more often than you realize!

We often have to create many objects of the same type. Say we have a website where people can browse dogs!

For every dog, we need object that represents that dog! πŸ• Instead of writing a new object each time, I'll use a constructor function (I know what you're thinking, I'll cover ES6 classes later on!) from which we can create Dog instances using the new keyword (this post isn't really about explaining constructor functions though, so I won't talk too much about that).

Every dog has a name, a breed, a color, and a function to bark!

When we created the Dog constructor function, it wasn't the only object we created. Automatically, we also created another object, called the prototype! By default, this object contains a constructor property, which is simply a reference to the original constructor function, Dog in this case.

The prototype property on the Dog constructor function is non-enumerable, meaning that it doesn't show up when we try to access the objects properties. But it's still there!

Okay so.. Why do we have this property object? First, let's create some dogs that we want to show. To keep it simple, I'll call them dog1 and dog2. dog1 is Daisy, a cute black Labrador! dog2 is Jack, the fearless white Jack Russell 😎

Let's log dog1 to the console, and expand its properties!

We see the properties we added, like name, breed, color, and bark.. but woah what is that __proto__ property! It's non-enumerable, meaning that it usually doesn't show up when we try to get the properties on the object. Let's expand it! πŸ˜ƒ

Woah it looks exactly like the Dog.prototype object! Well guess what, __proto__ is a reference to the Dog.prototype object. This is what prototypal inheritance is all about: each instance of the constructor has access to the prototype of the constructor! 🀯

So why is this cool? Sometimes we have properties that all instances share. For example the bark function in this case: it's the exact same for every instance, why create a new function each time we create a new dog, consuming memory each time? Instead, we can add it to the Dog.prototype object! πŸ₯³

Whenever we try to access a property on the instance, the engine first searches locally to see if the property is defined on the object itself. However, if it can't find the property we're trying to access, the engine walks down the prototype chain through the __proto__ property!

Now this is just one step, but it can contain several steps! If you followed along, you may have noticed that I didn't include one property when I expanded the __proto__ object showing Dog.prototype. Dog.prototype itself is an object, meaning that it's actually an instance of the Object constructor! That means that Dog.prototype also contains a __proto__ property, which is a reference to Object.prototype!

Finally, we have an answer to where all the built-in methods come from: they're on the prototype chain! πŸ˜ƒ

For example the .toString() method. Is it defined locally on the dog1 object? Hmm no.. Is it defined on the object dog1.__proto__ has a reference to, namely Dog.prototype? Also no! Is it defined on the object Dog.prototype.__proto__ has a reference to, namely Object.prototype? Yes! πŸ™ŒπŸΌ

Now, we've just been using constructor functions (function Dog() { ... }), which is still valid JavaScript. However, ES6 actually introduced an easier syntax for constructor functions and working with prototypes: classes!

Classes are only syntactical sugar for constructor functions. Everything still works the same way!

We write classes with the class keyword. A class has a constructor function, which is basically the constructor function we wrote in the ES5 syntax! The properties that we want to add to the prototype, are defined on the classes body itself.

Another great thing about classes, is that we can easily extend other classes.

Say that we want to show several dogs of the same breed, namely Chihuahuas! A chihuahua is (somehow... 😐) still a dog. To keep this example simple, I'll only pass the name property to the Dog class for now instead of name, breed and color. But these chihuahuas can also do something special, they have a small bark. Instead of saying Woof!, a chihuahua can also say Small woof! πŸ•

In an extended class, we can access the parent class' constructor using the super keyword. The arguments the parent class' constructor expects, we have to pass to super: name in this case.

myPet has access to both the Chihuahua.prototype and Dog.prototype (and automatically Object.prototype, since Dog.prototype is an object).

Since Chihuahua.prototype has the smallBark function, and Dog.prototype has the bark function, we can access both smallBark and bark on myPet!

Now as you can imagine, the prototype chain doesn't go on forever. Eventually there's an object which prototype is equal to null: the Object.prototype object in this case! If we try to access a property that's nowhere to be found locally or on the prototype chain, undefined gets returned.


Although I explained everything with constructor functions and classes here, another way to add prototypes to objects is with the Object.create method. With this method, we create a new object, and can specify exactly what the prototype of that object should be! πŸ’ͺ🏼

We do this, by passing an existing object as argument to the Object.create method. That object is the prototype of the object we create!

Let's log the me object we just created.

We didn't add any properties to the me object, it simply only contains the non-enumerable __proto__ property! The __proto__ property holds a reference to the object we defined as the prototype: the person object, which has a name and an age property. Since the person object is an object, the value of the __proto__ property on the person object is Object.prototype (but to make it a bit easier to read, I didn't expand that property in the gif!)


Hopefully, you now understand why prototypal inheritance is such an important feature in the wonderful world of JavaScript! If you have questions, feel free to reach out to me! 😊

✨ Twitter πŸ‘©πŸ½β€πŸ’» Instagram πŸ’» GitHub πŸ’‘ LinkedIn πŸ“· YouTube πŸ’Œ Email

Top comments (102)

Collapse
 
mukeshsharma1201 profile image
Mukesh Kumar

You should really make a tutorial for creating these beautiful Gifs as well :)

Collapse
 
lydiahallie profile image
Lydia Hallie • Edited

Lmao β€œhi guys welcome to my tutorial today we start off by having caffeine-induced insomnia and getting random ideas for animated gifs using Keynote at 4AM...”. But I may actually totally do it if it can help people :)

Collapse
 
iamsahithyan profile image
Sahithyan

yes. please do it. The GIFs are awesome. "Tell us how" in a video.

Collapse
 
combizs profile image
combizs

I just auth'd to the community so I can β™₯️ the parent comment and compliment how awesome the GIF is. easy to read, clean transition and carries the point across.

Collapse
 
savokiss profile image
savokiss

Please do it!

Collapse
 
kp profile image
KP

please do it!

Collapse
 
ivopauly profile image
Ivo Pauly

Please do it!

Collapse
 
mrmagician profile image
Avnish

Please do it

Collapse
 
ejbuggs profile image
EJ-Buggs

please do it! I just created an account just so I could comment, heart, unicorn, and save this for reference. Explaining things in such a visual way in beyond helpful. Thank you.

Collapse
 
tenxswej profile image
tenxswej

Hello πŸ‘‹ Could you please tell me which tool did you use to illustrate the codes in this post?? I really need this..

Collapse
 
amartya149 profile image
Amartya Aishwarya

Would love to see that tutorial

Collapse
 
meeru7 profile image
meeru7

hi, i am a beginner.
a question: what about Getters and Setters in reference to Constructor functions?
Please refer any resource specific to this.
Regards.

Collapse
 
pflash profile image
Precious adeyinka

Yes please, lydia I was just gonna ask it will mean alot to me, thank you mukesh for asking this question ur great mate!πŸ˜‰

Collapse
 
mjmhtjain profile image
mjmhtjain

i second that

Collapse
 
draczihper profile image
draczihper

Hey @lydiahallie I'm following up on the making gifs tutorial, did you make it?πŸ˜‚

Collapse
 
sebbdk profile image
Sebastian Vargr • Edited

Prototype, no one really uses it directly but it is one of the main architectural points of the language...

Instead we now have class, because, then we can look more like C# and Java, yay for pointless uniformity!

I wonder how pop JS would have looked today if we didn’t have all the baggage from poorly researched classical languages. :)

Collapse
 
jankapunkt profile image
Jan KΓΌster

I already mentioned in another discussion that still I wonder why prototypical inheritance is rarely taught at CS or SE classes. It's a very strong paradigm and mostly misused due to misunderstanding.

Collapse
 
sebbdk profile image
Sebastian Vargr

Having used JS’s version 10-12’ish years ago days I can definitely understand why.

I had a lot of problems making it have good verbosity, I might give it a go again sometime, back then I was kind of a rookie. :)

That being said, I think it comes down to familiarity, most languages are made to resemble classical OOP and their structures, the commonly accepted truth has been that is was the most optimal way.

But if we look back, most of those features were based on popularity and not research on what would be better to manage state, have high verbosity etc.

Just look at Java literally founded on hype, but I digress, I am seeing a strong pull towards more diverse paradigms, it will be interesting to see were that takes us. :)

Collapse
 
mickmister profile image
Michael Kochell

It reminds me of how interpreters evaluate variables through different closures/scopes. If it's not in this scope, let's check the next one, and so on. Once we've checked everything up to global scope and still haven't found the variable, it is considered undefined. Very useful information.

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
sebbdk profile image
Sebastian Vargr

Not really, but I can see how you could interpret it like that.

I’m not sure how to help you understand how proper debate is done in this context.

But an accusation without argumentation is a really bad way to start a conversation. :/

Honestly it pissed me off a bit.
But maybe we can turn this around?

Thread Thread
 
Sloan, the sloth mascot
Comment deleted
 
lydiahallie profile image
Lydia Hallie

Okay let’s stop this discussion here or continue on hackernews lol

Thread Thread
 
sebbdk profile image
Sebastian Vargr

Actually yes, you could have asked for sources, and I could have given them.

Instead you decided to attack my intentions, which you have no way of knowing.

Please think about this before you comment more. I’ve given up my initial annoyance/insulted feelings, that was not easy, you clearly have not.

I’m not trying to keep some kind of moral high ground here, but I don’t know were to meet you if you keep this level of unwillingness to have a constructive debate.

Thread Thread
 
pablorn profile image
Pablo Reyes

In the end you married or no?

Thread Thread
 
dexygen profile image
George Jempty

Why did you necro this?

Collapse
 
vncz profile image
Vincenzo Chianese

It'd probably be a better language.

Collapse
 
emmabostian profile image
Emma Bostian ✨

You have a true gift for blogging. Keep on writing!

Collapse
 
artoodeeto profile image
aRtoo

the GOAT! suggestion for the next topic is this. hehe. thank you for this. :)

Collapse
 
lydiahallie profile image
Lydia Hallie

Good idea!

Collapse
 
ptejada profile image
Pablo Tejada
Collapse
 
adriaanbd profile image
Adriaan Beiertz

Excellent articles, excellent visuals. Here's a resource I used to drill this down, with excellent explanations and visuals as well: objectplayground.com/

Collapse
 
pencillr profile image
Richard Lenkovits

This is awesome. It made me realize again that there are a lot of things I 'just use' without understanding it. Which is bad. :D

Collapse
 
focus97 profile image
Michael Lee

Came here with a "yeah, I understand JS prototypes but a visualization could be cool" and then realized how much this exceeded expectations. Great job with not just the explanations but also the animated graphics. Nicely done indeed.

Collapse
 
umashankar profile image
umashankar

It was Yesterday, when i was working on project. Inspecting Front-end code with google chrome dev tools and this thought struck my mind who would've written all these codes,where they came from.

thepracticaldev.s3.amazonaws.com/i...

And this day i found this article explaining everything very beautifully.
Thank you!

Collapse
 
nanouchkaya profile image
Claudine

Thank you so much for this awesome tutorial! Well explained. I finally understand what all those _proto_ mean in my console πŸ˜‚

Love your gif, they're very practical for understanding.

Collapse
 
charanweb profile image
CHARAN

Best article with visualize so great.Im a begginer,Classes are very new to me . By reading this article, I understand very clearly.All the concepts are animation.Thank you so much Mam❀️❀️. It helps me a Lot

Some comments may only be visible to logged-in visitors. Sign in to view all comments.