Check out a free preview of the full Deep JavaScript Foundations, v3 course
The "The Prototype Chain" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:
Kyle constructs a diagram of the relationships within JavaScript's prototype system.
Transcript from the "The Prototype Chain" Lesson
[00:00:00]
>> Kyle Simpson: So again, follow along with that code on the slide. And I'm gonna be diagramming it for you and we're gonna go line by line and create the entities. Before we even get to line one, we need to diagram a bit about what's happening in line zero, in other words, what's happening before your program has even started to run.
[00:00:18]
And in this diagramming I'm gonna use a very simple notation which is I'm gonna use squares to represent objects and circles or whatever I can approximate thereof to represent functions. I am drawing with a trackpad so it's not gonna be great drawing please forgive the quality of my artwork.
[00:00:37]
I'm going to diagram first the lines zero environment i'm going to do that by drawing a line across here that basically says everything above this line is the line zero environment, and then below it is where we'll diagram the program. Above this line in our line zero environment, there's one very critical entity.
[00:00:57]
It is a function, so I will draw it as approximately a circle and it goes by a pretty familiar name, it goes by the name capital O, object.
>> Kyle Simpson: And I'm just gonna abbreviate cuz I don't like writing out this whole words, but it's called object, capital O object and that's a function that exists.
[00:01:18]
And you all have seen that that's one of our fundamental objects that's built into the language, probably one of the most important of those. We have capital O object there, and by the way, it has several things on it. It's got object.keys and object.values, and various other utilities.
[00:01:36]
So it's not only a function, but it also serves as a namespace to have other methods on it. So there are a bunch of really important general utilities that we use across JavaScript, that are located directly on that function. But there's another entity that exists and it is a square.
[00:01:53]
So I will draw a square here, something like a square. And it is probably the most important object in all of JavaScript. It's so important in fact that we don't even have a name for it. We can't come up with a good name for it. So you know how we name it, is we name it referring to what points at it.
[00:02:18]
There's a property on the object function that points over at this thing and that property is called prototype. Writing is really painful here. I'm just gonna abbreviate with proto here. It's called prototype. That is the name of that property. So if you've ever seen object.prototype, that's the property pointing from the object function over to this thing called object.prototype.
[00:02:46]
And there's a bunch of really important stuff on object.prototype, like toString, and valueOf, and all these other fundamental utilities that exist in our language. All non-primitives descend directly from this object.prototype, so it's a really important object.
>> Kyle Simpson: There is one other thing that exists in our line zero environment which is a property that's pointing back the other direction.
[00:03:11]
It's pointing from here over to here and that property they chose a really perplexing and frustrating name for. They choose a specific name because what they were trying to do was essentially lie to you, to pretend as if JavaScript system had classes so they choose to name this constructor.
[00:03:35]
And I'm just going to write c-o-n to abbreviate. It's called constructor. So you have this object.prototype which points at this object, and if you had that object and then said .constructor, it'd be pointing back at this object function as if the object function was the constructor of the object that pointed to it.
[00:03:58]
But that work constructor in the fundamental prototype system has no more meaning than the word fubar. Other than to convince you, that this is a class system because it has constructors in it and we will see a bit later that's what constructor basically comes in and pretends it, it helps the artifice if you will, that we are dealing with a class system.
[00:04:23]
So that our line zero environment. Now I'm gonna start diagraming again with the same notation but I'm gonna start with line one. On line one, we have a workshop function, do I'm gonna draw a circle and it's called workshop. But I'm just gonna abbreviate w for workshop. That's the function that exists on line one.
[00:04:44]
But also what exists on line one, that is not obvious, is that there is another object that has been created as a result of line one and that object is also pretty important. At the moment it's empty but it's gonna serve a pretty important purpose except it's so important that we don't have a good name for it.
[00:05:04]
And so we refer to it by the property that points at it. And I bet you can guess what that property's called? That property's called proto, prototype, okay?
>> Kyle Simpson: I could probably be using the text tool, but I just didn't wanna mess around with switching between tools. So that's called prototype.
[00:05:26]
So we refer to that object as workshop.prototype, which is what you see on line four, workshop.prototype. It's a bizarrely named word like where does prototype even come from? I've tried to search for the origins of prototype within computer science, and it's a murky etymology at best. I can't come up with why we use this word prototype or what it's even supposed to mean.
[00:05:49]
But there is one other thing that exist on this line one, which is that there is a linkage from here back to here, there is a property pointing back, and that one is also called constructor.
>> Kyle Simpson: And again, that exist only for the purpose of trying to pretend to you that, that object was created by the workshop function, as if the workshop function is a constructor for classes.
[00:06:17]
And one final thing that exists, there is a hidden relationship between this object and this object. I'm gonna do it, if I can, with a dotted line. There's a hidden relationship between those two. We'll come back to that relationship later. But all that's a result of line one.
[00:06:42]
You follow me? All right, let's move to line four. We'll come back to two later. Let's move to line four. On line four, we make a property and add it to workshop.prototype. It doesn't matter that it's a function at this case. So I'm just gonna literally write it in.
[00:06:58]
We're just adding a property called ask directly to this object. You with me? That's what line four does. We'll skip down to line eight. That's what's really interesting. And I wanna review, if you wanna pull up a slide or flip back in your slides, there were four things that happened whenever the new operator was put in front of a function call the way it is on line eight.
[00:07:24]
Now we want to do those four things and I'm gonna diagram each one of them. So number one, the first thing that happens when new is put in front of a function call is that it creates a brand new empty object out of thin air. So here is my brand new empty object out of thin air.
[00:07:42]
And then it links that object to another object. So here I'm gonna do a linkage, this little hidden linkage with the dotted line. It links that object to another object. Number three. It invokes the function that it was called in front of. It invokes that with the this keyword pointing at the object.
[00:08:05]
So here we are, now, I'm gonna move to line two, and the this keyword is pointing at this particular object, and what does it do? It adds a property called teacher, so we're gonna put teacher directly right here on it, and I'm just gonna abbreviate that with t-e-a.
[00:08:25]
We put teacher directly on that object. That's what line two does. Everybody following me? Now the fourth and final that the new keyword does, when it returns it back, if the function does not return an object, which in this case it does not, the new keyword assumes that you meant to return to the this keyword, that brand new created object so that's get returned back and it gets named deepJS.
[00:08:51]
So this object is called deepJS. I'll call it deep. That's what happened with line eight and if you understand what happened with line eight the exact same thing happens with line nine. So I'll simply draw it in.
>> Kyle Simpson: My drawing is getting much worse. And then it gets the teacher property added on to it and it comes back and it's called in this case reactJS.
[00:09:33]
So I'll just say R-e for reactJS. That's that object from line nine. Everybody understand where these entities are coming from and what their relationships are? Okay, so let's look at line 11. On line 11 of that code snippet, we say deepJS.ask. Does the deepJS object, this object right here, does it have an ask method?
[00:09:58]
It does not. So why is it that we're able to call that method? Because our mental model if we were thinking about these as classes is that the ask method would have been copied to the instance but it isn't there. Instead, what is gonna happen is that internal linkage, which is called the prototype chain, in Speck, they use bracket, bracket prototype.
[00:10:22]
It's called the prototype chain, and so internally there's a linkage from the deep object, this one right here, up to this object. So when we look for a property on an object and it doesn't exist, by default, what we do is do do do do do do do.
[00:10:38]
We walk up one level to the next object in the chain and we ask if it has that property. Which in this case, it does. It has an ask method. When we invoke the ask method, which was line five essentially, what is the this keyword gonna point at?
[00:10:57]
Which object is the this keyword gonna point at? It's gonna point at this object. Why? Because the call site is line 11. The call site says invoke that function in the context of deepJS. It doesn't matter where we find the function from. In this case, we found it up the prototype chain, but it doesn't matter, we still use the call site to invoke it.
[00:11:20]
You're not used to generally thinking this deep about the plumbing of JavaScript. But I think it's important, critical that you not have incorrect models of thinking. All right. So if we can say that with deepJS, we can also say that with the react object. The react object on line 14 when we say .ask, the exact same thing happens.
[00:11:43]
We don't have an ask method but we go do do do do do do. We find the ask method when it is invoked, it's this keyword is pointing out our object so when it says this .teacher which property is it accessing? This one right here.
>> Kyle Simpson: That's awesome right?
[00:12:01]
We're able to share one method with potentially an infinite number of instances and they're all able to share it because of the this binding behavior and that prototype linkage. It's actually a really awesome system. I'm not at all saying that the prototype or the this keyword system is bad, I'm only saying that maybe it's a little too limiting to try to think about this only through the lens of classes.
[00:12:27]
Maybe the system is actually much more powerful than the class design pattern. If you switch to your next slide you'll see the diagram of the buildings. And I'm gonna switch back to the slides now, so if you wanna copy this down or not copy it down that's okay, my little bad drawing.
[00:12:47]
But now at least you understand where some of those fundamental behaviors are coming from, those relationships are coming from.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops