Get the fundamentals down and the level of everything you do will rise. - Michael Jordan
Continuing on day 4 of posting my notes on this this blog as I learn to master Javascript fundamentals one day at a time.
As stated in my original post, I do 1 hour of video lessons from Watch and Code every day. If you're interested in learning Javascript in a way that goes beyond basic tutorials and gives you a foundational, practical knowledge without relying on frameworks - I'd highly recommend it. If you're reading these posts, please keep in mind that these are just my notes, and I'm not an expert (yet!). If your goal is also to master the fundamentals of Javascript, please head over to Watch and Code and start your journey there!
All screenshots were annotated using Shotty.
Prototypes: An Introduction
Prototype:
"The original or model on which something is based or formed".
dictionary.com/browse/prototype
After learning Prototypes, we will have learned all the major features of Javascript. Which is a big milestone.
We need to know about prototypes to read Accounting JS, so that's why we're learning it now.
Imagine we have two dog objects:
We can quickly see that they only difference between these two objects are the names. The fetch method is the same, but what if we wanted to change the fetch method in the future. When we look at these two objects as programmers, we see their similarity, and we wonder if we can separate they similarities out into a different object, and then all dogs can share that object.
You can see in the diagram above that now we've broken the commonalities out into a separate object. We've deleted fetch from myDog and randomDog, and we've put it on the dog object to avoid redundancy.
But now we have a new problem: How do we create a link between these dogs and their abilities? (Their ability to fetch).
We want to tell Javascript the dog is the model on which myDog and randomDog are based.
Javascript has great feature for doing exactly that, and it's called "Prototypes".
So we tell Javascript to build myDog and randomDog based on dog, as is illustrated by the two arrows above.
Now myDog and randomDog can access the fetch method, as if they had that ability all along.
The advantage is that we don't repeat the data on every single dog, it's saved in one shared place.
So that's the concept, let's see how we actually use Prototypes in Javascript. It's pretty simple.
There are only two main methods you need:
- Object.create(dog);
- Object.getPrototypeOf(myDog);
So let's recreate in code what we have in our diagram.
First, we need to start with the base. We have to start with the dog object. So let's create dog.
var dog = { fetch: function() { console.log('fetch'); } };
Now let's create the specific instance, "myDog".
var myDog = Object.create(dog); myDog.name = 'Alexis';
In the first line, we create a new object, setting the prototype of that object to dog. This line is what builds this arrow from our diagram:
Then in the second line:
myDog.name = 'Alexis';
We're setting the unique data of that particular instance of dog.
We can do the same thing to create another instance of dog -- randomDog.
var randomDog = Object.create(dog); randomDog.name = 'Hey';
That's it. That's how you use Object.create.
Now you can access properties on the dogs using normal dot notation.
But the unique thing about prototypes is that myDog and randomDog can now access fetch as if they have that method too, even though we never explicitly wrote those methods when we created myDog and randomDog.
The reason this works -- what Javascript is actually doing -- is that when you run randomDog.fetch(), Javascript is going to first look for fetch on randomDog and see that the fetch method is not there, but because you set up the prototype link, it will look at dog and find the fetch method.
So that's the first of our two requirements:
- Object.create(dog);
- Object.getPrototypeOf(myDog);
Now let's look at getPrototypeOf().
If we use getPrototypeOf on myDog like so:
Object.getPrototypeOf(myDog)
We know it will return dog. We can confirm this if we run the following equality:
Object.getPrototypeOf(myDog) === dog // true
That's the main idea behind prototypes: you can build objects that are based on other objects.
But there's actually one layer that's missing to our diagram. Lets see that last layer. It's a hidden layer that most people don't know.
It's something that happens automatically in Javascript whenever you create an object using curly braces.
// Automatically set the prototype of the object to the default object prototype. var dog = { fetch: function() { console.log('fetch'); } };
This inheritance means that even though we may define a very basic object:
var basicObject = {};
It can still access all the methods on the prototype object as if it had them too.
Which is why we can do stuff like hasOwnProperty:
basicObject.hasOwnProperty('name'); // false
And if we actually create a property called name and give it a value:
basicObject.name = 'Jacob Ruiz';
Then hasOwnProperty will return true:
basicObject.hasOwnProperty('name'); // true
Summary:
- Prototypes allow us abstract commonalities between objects out into a prototype object so they can be "born" with certain data and abilities.
- It allows us to avoid repetition.
- Even the most basic object already has a default object prototype that gives it certain "innate" abilities like "hasOwnProperty", and other methods.