Let’s talk data
String, Number, Boolean, BigInt, Symbol, undefined, and null
… and two “structural” types…
Object and Function
As you probably already know, each data type has some inherent functionality. For example, a string can tell us how long it is if we simply ask it about its “length” property.
An array can describe its own length, too!
Arrays even come with their own built-in methods that we can access such as map, sort, and reduce
It’s not like we ever told the string or the array what its length is — they already knew those things. Same thing with the map method — we never exactly taught the array how to use it.
If we didn’t write this functionality ourselves, it must have come from somewhere else. Answering the question of what and where that “somewhere else” is will be the main objective of this article.
Inventing our own data type
To show how this works, we’re going to pretend to invent a brand new data type. I like football, so let’s make a fake FootballPlayer data type and define it using a function
In the above example, FootballPlayer is our fake data type and peyton is an instance of FootballPlayer. Since our FootballPlayer datatype definition is just an empty function with no functionality or properties, peyton can’t tell us much right now.
But this only gives the peyton instance a career property, not the FootballPlayer constructor. It would be very annoying if we had to manually define the career property of each FootballPlayer instance.
To fix this, let’s re-define our FootballPlayer constructor to give every instance of FootballPlayer a .career attribute set to “football.” Let’s also give each instance of FootballPlayer the ability to score touchdowns with a .scoreTouchdown method.
Whenever we create new FootballPlayer instances, they’ll now have access to the .career property and .scoreTouchdown method.
What if we want to add even more properties and methods? While we could again redefine our FootballPlayer constructor with a .salary property and a .getPaid method…
We’re going to handle it a different way. Introducing prototypes.
Let’s go back to our simple FootballPlayer constructor and create another peyton instance with no properties or methods:
Piecing things together
The reason we walked through the above example is to demonstrate the following. This code below…
… is basically the same thing as this code…
When we created our FootballPlayer constructor and created new instances, the instances inherited whatever methods we had built into the FootballPlayer constructor prototype.
Just like our FootballPlayer instances inherited the .throwDeep property we added to the FootballPlayer prototype, our String instances inherit from the String prototype. What methods and properties are inside the String prototype??
Arrays? Same story