7.2 Prototypes - Video Tutorials & Practice Problems
Video duration:
8m
Play a video:
<v Instructor>If you look around online</v> for descriptions of JavaScript's object system, one of the words you'll come across pretty quickly is the word prototype. If you look at the text, you can see a description of prototypes from the Mozilla Developer Network and it's worth reading that, but I don't think anybody ever really understood what prototypes are by reading a paragraph. What you really have to do is see some examples. Looking at one representative example, is the purpose of this section. We'll start by moving the processed content variable into its own method. Logically, it is a separate operation and this is just the sort of thing we might want to change later on, which in fact we'll be doing in just a moment. This gives us another example of defining a method. So we can move this up here. It's gonna be the same thing, this.processedContent equals a function which we'll also call processedContent, but we could call anything. This is an internal name to the object. And to now process content, instead of being a variable is a function of zero arguments internal to this object. So down here, we'll change processedContent to this.processedContent(), with parentheses, and same thing in here. We'll see in a minute, what good this does us. But for now, let's make sure it's still working. (keyboard clicking) Oops, what do we do wrong? Aha. This is a function. I forgot to return the value. I said, "What did we do wrong?" You might have caught this mistake. This is why you test it, 'cause you never know. Of course it's inconvenient to test it in the REPL like this. Be really great if we had an automated way to do this, and we'll be talking about that in the next chapter. So especially inconvenient that we can't just up arrow. Can copy and paste though, like this. All right, that's working. Now, let's define a second object. One that will help us understand what a prototype is. This object will be a translated phrase. It will be a phrase that has two arguments, content and a translation of that content. Let's do this here. So translated phrase will take into content, argument, and a translation. And we'll just assign these here, like this. Now suppose we wanted this translated phrase to have a processedContent and a palindrome method. Well of course we could just copy and paste these, that would work. Translated phrase has a content property, so this would work just fine. But of course it's repetitive, so what JavaScript allows us to do is assign the translated phrases, prototype to a new phrase object that automatically allows it to call these methods. So let's take a look at that. Where we do that is like this, TranslatedPhrase.prototype, is equal to a new phrase. It's a result of this, when we call a new translated phrase the resulting instance object will have both the processedContent, and more importantly palindrome methods. In many languages, this sort of arrangement is called inheritance, because translated phrase inherits methods from a parent object. So let's take a look in the REPL again. Let's introduce a new variable called frase, just the Spanish word for phrase. We'll have the English word recognized in the Spanish translation, which is reconocer. All right now we can ask frase whether or not it's a palindrome, because of it's inheritance. It inherits palindrome from the phrase object. And it's false because recognize is not a palindrome. But, what if we wanted to use the translation instead of the content for determining whether or not a translated phrase is a palindrome. In order to arrange that what we can do is override the process content method in the parent object. And instead of using content, we can use translation so we can copy this, put it in here. Instead of using this.content we can use this.translation. So what'll happen here is when we call the palindrome method on a translated phrase, it will look for a palindrome method, which doesn't exist in the translated phrase. So then it will go up to the one in the phrase object, but then it will still say, "Hey, is there a process content method in translated phrase? Oh, there is. So I'm gonna use that one instead." And the result is that the translation is the one that will determine whether or not it's a palindrome. Let's take a look at that in the REPL, copy and paste. Again, this is inconvenient, automated test for the way to go in real life, but that's for next chapter. Okay, so we've got that. And we can do... Remember if we do let a second time it'll give us an error. So let's just redefine what frase is. It's actually the same thing. We needed to do this though, because translated phrase had changed. We changed the definition. So we had to do new translated phrase again. But now if we do this... Well reconocer, as it happens is a palindrome. So this should return true. Look at that. So these ideas of inheritance and method overriding are important aspects of object oriented programming. It allows us to reuse functionality in this case, the functionality and phrase while selectively overriding that functionality in particular cases. In this case, allowing us to use the translation to determine whether or not a translated phrase is a palindrome. And the way we do that in JavaScript is by signing directly to this prototype, which is why JavaScript is sometimes called a prototype based language. This inheritance relationship is then sometimes called the prototype chain.