Hi, and welcome to my first multi-part blog post! This week and next I’ll be talking about two types of inheritance in JavaScript: inheritance through prototypes and constructor functions, and inheritance through classes. These articles are for anyone that wants to gain a better understanding of these topics, as classes are a basic programming paradigm that’s important to have a strong grasp on, and prototypes are important to understanding JavaScript. These articles are also for myself; practicing explaining concepts in layman’s terms is imperative to solidifying one’s understanding of those concepts. I hope that by explaining these concepts to you I will better understand them myself. I won’t be covering everything about prototypes and inheritance in this article, but I’m confident readers will finish having learned a thing or two about JavaScript.
As always, I’d love to hear some feedback. Comment here, or reach out to me through email, Twitter, GitHub, or my LinkedIn. As of the writing of this article I am actively looking for work. Don’t hesitate to reach out if you’d like to get in touch concerning an employment opportunity.
Inheritance in JavaScript
Inheritance in JavaScript refers to the ability of objects to inherit properties from other objects. Objects in JavaScript belong to what is called the prototype chain. Each object in JavaScript has a property that chains it to another object, its prototype. The prototype chain ends with null, which is what the Object class inherits from.
When you make a new object in JavaScript, that object inherits certain properties from the Object class. We can see what new objects inherit from the Object class by typing the following in our console:
Therefore, we can see that all objects that inherit from the Object class will have the properties constructor(), hasOwnProperty(), etcetera. We can define our own constructor function that creates instances of the Object class, but with their own properties:
Here we defined the Plant constructor function. This constructor function takes one argument, color, of which each instance of Plant will have its own value (defined as this.color in the constructor function). Calling Object.getPrototypeOf(fern) (which is more or less the same as fern.__proto__) returns its constructor function (constructor) and the properties it has inherited (__proto__).
This is where the fun begins: now we can add properties to the Plant constructor functions prototype property that will be inherited by all instances of the Plant constructor function, regardless of when they were made. Let’s add a function property to the Plant constructor function’s prototype property:
This is a great way to show the difference between .__proto__ and prototype. prototype is what we use to define properties that we want instances of a constructor function to inherit. In this case, we added the function logMyColor() to the prototype of our Plant constructor function. That caused all instances of that constructor function, currently only our instance called fern, to inherit that function in their .__proto__ property. It’s important to note that fern does not have the inherited function on itself, only on the .__proto__ property. This proves that our instance of the Plant constructor function, fern, in inheriting properties of the constructor function’s prototype property.
This also shows how when we call a value of an object, JavaScript first looks for that value on that instance of the object. If it can’t find it, as is the case with our fern object here, it looks at what that object inherits from, in this case our Plant constructor function (or more specifically, its prototype property). If it can’t find it there JavaScript will continue looking up the prototype chain until it finds that value or ends at null. Let’s check to make sure this is true with the following:
So we can see that fern has the color property, and we can call that property and see its value. We can check if fern has the property logMyColor and see that it does not have that property, but we can still call logMyColor() on our fern! Well, if it doesn’t have that property, but we can still call it, it must be.. I don’t know.. Inheriting (!) it from somewhere!
If fern is an instance of the Plant constructor function, it must be inheriting logMyColor() from Plant, right? Well, kind of. It’s not inheriting it directly from Plant, but from Plant’s prototype property. So when we call logMyColor() on fern, JavaScript sees that fern does not have that property, then looks at its constructor function’s prototype property, Plant.prototype, for that property. In Plant’s prototype property JavaScript finds and executes logMyColor().
On .__proto__ Versus .prototype
.__proto__ is what we use to refer to the prototype properties instances of objects inherit, and is roughly equivalent to Object.getPrototypeOf(obj). .prototype is the property of our constructor function that holds values we want instances of that constructor function to inherit. However, values given to objects when they are created (like color) belong to that object, and values added to the prototype of the constructor function that created that object are inherited (like logMyColor).
That’s All Very Cool, But Why Is This Important?
That’s a great question. Understanding prototypes in JavaScript is important because it is one of the qualities unique to JavaScript, and it is in reality how classes in JavaScript work. I’ll talk more about this next week, but in the ECMAScript 2015 (also called ES6) release of JavaScript, the almighty JavaScript developers added the ability to create classes, just like all the other cool programming languages around had been doing for years. That’s right, it wasn’t until 2015 that JavaScript gained the ability to create classes. But JavaScript’s class syntax is really just syntactical sugar, because behind the scenes it’s just making constructor functions and instances of objects, literally exactly what I showed above.
So Where To From Here
Man, there is so much more to learn about prototypes. If you want to know more, check out the links below to continue your reading. The biggest takeaway should be that prototypes exist, you may not see them much anymore, and if you want to create a class system, use JavaScript’s classes instead.
Next week I’ll be tackling the topic of classes in JavaScript. That article should be considerably easier to write, and in contrast to this article, probably make a lot more sense!
If you liked this article and want to discuss it further please feel free to reach out through one of the avenues below. The tech community has been nothing but warm and welcoming to me and I want to pay that forward.