Check out a free preview of the full A Tour of JavaScript & React Patterns course

The "Prototype Pattern" Lesson is part of the full, A Tour of JavaScript & React Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Lydia outlines the prototype pattern which is more memory efficient than the factory pattern because it avoids the duplication of shared properties and methods by elevating them up the prototype chain. The prototype pattern can be used with the Object.create method or with ES6 classes.


Transcript from the "Prototype Pattern" Lesson

>> All right, so next is the prototype pattern. And this is probably a pattern that you have used many times when working with JavaScript, but you may not have known it. So what we saw with the factory pattern is that it's pretty easy to have many of the same objects.

For example, in this example, we have a factory function like createDog [LAUGH]. So we wanna create many dogs, maybe we have a name and an age. And also, all dogs can bark when we console the name is barking, and we have wagTail. Now, this is totally doable. It's fine, this works.

However, what's happening here is that whenever we are creating those new objects, for every object, we're also allocating memory for all the functions here. So even though the whack tail and bark functions are identical for all the objects, we're still allocating new memory for each and every one of them.

So this is not very memory efficient. Now, instead, what we can do in JavaScript is use something called the prototype pattern. And this is where the classes come in, because everything on a class that's defined directly on the body is considered to be a part of the prototype.

And the constructor is the individual, or the unique object that gets returned. So any functionality that is shared between those many objects can be defined on the class body. So what we see here is that we've now moved the bark and the wagTail methods. Instead of having them directly on these objects that we created, we now go up the prototype chain, as to say, or go down to prototype chain.

People use them synonymously. And instead, it's now on that dog prototype. So whenever we invoke a function here, I think this is just an example. So we can just say a dog1 or 2, and then bark index.js. So you can see here that we've created many new dog instances that just say name, age.

Actually, I will show this in a browser console, because they're just a bit better at showing the prototype, so you can kind of see what's going on here. I'll just open it in here, if that's all right. I'm just going to do, Okay, so we've just created many new dogs, again, dog1 and dog2.

So when we just logged dog1, you can see that there's only name and age. Now, you might think okay, but whereas it was bark and wagTail, cuz we can still use that. Now, whenever we log this dog again, I'm just going to clear this just to make it cleared up.

I'm just going to make this a bit bigger. You can see that there is a prototype object, yeah, these logs. And this prototype object is essentially, like you can see here, it looks very familiar to the dog we just created, cuz we had a constructor. And then we also added the bark and wagTail methods to this class object.

So here we can see that bark and wagTail. Those methods are available on the prototype. And this prototype is shared among all the objects that we just created. So any dog instance, or any instance from the class automatically also has access to those methods. And we don't have to worry about allocating a space in memory for those methods, because we can just add it to the prototype Now, yeah, like I said, having that prototype pattern is extremely memory efficient, because we don't really have to worry about duplication.

But you can also extend classes kind of infinitely. In which case, it can be pretty difficult to kind of understand where certain properties may be coming from. I don't know if it's clear. But for example, you have a border collie, or we have an animal class, and all animals have a name and a cell counts that's kind of unique to an animal.

Then we also have mammals. Now, a mammal is an animal, so it should have all the properties of an animal, but a mammal also drinks milk. So for that specific mammal, we have to drink milk method. And then we have canine, which is a mammal, so it can drink milk, and it has a name and a cell counts.

And it also has a smell method, and so on, all the way down to dog, which can wag its tail, and then a border collie, which can hurt sheep. So they get more and more explicit every time, or unique. But of course, if we have that new border collie, and we get the property cell count, it can be like, okay, where did that come from?

Is that on the border collie? And then you have to go all the way down that prototype chain. Now, when I said you've probably used the prototype pattern how many times before is because whenever we have, I don't know, any object. So const person is { name: "Lydia" }.

So on this person, you will also find a person, because everything that we create in JavaScript, or all the objects that we create in JavaScript automatically inherit from that object prototype. So this is why we have all this functionality that you may have seen whenever we're using any type of data type on an object, like toString or valueOff.

So even though we didn't determine that on the object itself, JavaScript has gave that to us because it's an instance from that object class. Now the same goes for I think string, we have all that primitive data types. I guess if we have name, I guess you cannot really see like that in the DevTools we get, so that has new string.

I think maybe this is a prototype or something. I don't know, I don't know how you can see that in DevTools. That's essentially where we get all those built-in methods from, it's from those primitive data type prototypes. So what we saw with factory pattern before is that it might have been better if these objects that we created here had some kind of shared properties.

I'm just trying to find the, yeah, here. I mean, in here, they're all unique. So it doesn't necessarily make sense to use a prototype pattern here because there is nothing to share among all those objects. They all have unique values. Book Two title is not the same as Book Three title.

But maybe if they had some kind of method, I don't know what method could be on a book, ad sale or something, or sell, I don't know. It's something that is shared among all of them, then a prototype pattern would've made sense. Yeah, so in there are actually many ways to create a prototype either just with a class, or with the object.create method.

Yeah, but I'm only showing examples with a class here, just because it's a bit more readable, in my opinion. Yeah, so I think then we're done with the exercise. So we have a factory function here again, which creates a user, and we only pass a firstName, lastName and email.

But on every user, we also have some functions, or some methods like checkLastOnline, sendEmail and delete. So instead of creating a factory function here, I want you to use the prototype pattern to create those users instead, and be a bit more memory efficient with everything.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now