So if I were to call this increment function again, let's go ahead and clear this and run. You'll notice that now it will count to two. So the second time this function was called, the myNumber variable had already been incremented to two and then when we run this console.log, it's displaying that value. So I could keep on doing that, and that function is going to keep on remembering the value of my number, which changes as we run the different copies of that function.
Now, closures are also common inside object definitions, and they can show you a little bit better how the closures can remember the state. So let's take a look at an example of that. So, here's a separate function that does something pretty similar. It just adds numbers up. Now, this is a little bit different, because we have this in object notation here. So we've created an object and we've assigned that object a myValue variable, which is initialized in one, and then this object returns two different methods.
This display method which just shows you the value of the variable called myValue here, and then this increment method, which adds one to that value. So, if we create a variable right here called mything, and we assign that object to that variable, this mything will essentially be an instance of this object. So if you use the display method, what's going to happen is it's going to display the value of my value right here.
Now, if I run the increment method, of course, then it's going to increment that value, and if I display that again, it's going to show the new sort of version of that value. I could just grab a couple of these and let's go ahead and paste 'em and clear this out and run. You can see that now it's incremented it to three. So every time I'm calling the function, even though the object has already been created, these methods are actually changing the value of this variable right here.
And the interesting thing is also that if I create another instance of that object... Let's go ahead and copy this, and we'll go ahead and change these to other for this other variable. Let's go ahead and clear this out and run. Notice that when it displays the value of other right here, it's displaying it with the value of this variable being one, again, because this is a different instance of the object.
So this myValue is only available inside each of these different objects or the instances and they are uniquely incremented by these different methods. Now, it's only one here because we didn't really display the increment, but you sort of get how this works. One thing that you have to be careful when using closures is what happens inside loops. Since closures remember the value of the environment that they were created in, inside loops, those variables are constantly changing.
That's what loops do. And by the time the closures are called, the loop has already modified the values within that loop. So let's take a look at how we can work around it, and before I do that, this technique is actually called a function factory. It's a technique where you create a loop to create a series of functions. It works really well for creating a series of events. So let's dig into a more practical example. I've got a form right here, and I want to create some different alerts with data that I want people to enter into these text area fields.
So this is a pretty simple sort of form, and I'd install Bootstrap here just to make things a little bit nicer, and you can see that we've got just a form and a couple of form elements, nothing too special right here. So, we'll go into the script, and you'll see that I've created a couple of attributes in this item text object, and it's essentially going to hold the ID of the element that we want to modify as well as the text that we want to display in each of these objects.
So I could sort of create some different texts for a very large form that somebody has to fill out, perhaps a medical form, and what I'm doing here in this function is taking care of displaying the elements. So this is just a series of calls that select one of these items and then inserts a node that shows these text elements. So this is not really that interesting to worry about. All the interesting stuff is going to happen right here.
So what I want to do is create a series of events that are going to track me clicking on these different elements. So we'll do that inside this setup item. I created a variable called DOMElement that I want to target the elements that I want to get, so what I'm going to do here is create a variable that is going to be the length of the elements that we have. So essentially this item text, remember, is this sort of object with these elements, and so I want to loop through those items, and in here, I want to go ahead and select the different elements.
So I'm going to do a DOMElement here, and that's going to be equal to the element I want to choose. So document.querySelector, and I'm going to look for the itemText ID. All right, so this DOMElement is going to have a node that is pointing to each one of these different item IDs, which correspond to elements in the form.
Once I do that, I can add a set of event listeners. So I'll do DOMElement.addEventListener, and I'm going to look for a focus event listener. So when somebody clicks on either one of the different text areas, then I'm going to create or actually execute a function that I'm going to create. So I call initItem, and I'm going to pass along the ID of the element as well as the text. So that's in itemText, and since we're in a loop, it would be [i].id and itemText[i].text.
Let's go ahead and make this a lot lighter so we can see this a little bit better. So what we've done here is created a series of listeners that are going to listen for clicks inside those different elements. Now, I've created this item here called initItem because this is a loop, and if I don't do this, and I try to create a function, say, like a callback here, then because this loop is executing constantly, the closure would receive the last value of those elements.
So I have to create sort of an in between function here, and I'm going to do that here. Function initItem, and I'm going to just pass along the ID and the text here, and all this in between function is going to do is to return, and this is actually the closure. We're going to return a function that is going to call the handleItem and pass along the ID and the text as well.
So, let's go ahead and save this, and we'll make our window a little bit smaller. And now you can see that when I click on these different elements, the different pieces of text will be injected into our form. So the interesting thing here is that this closure is allowing the state of our loop here to be remembered. So it remembers when it creates these different events what the state of the text that's supposed to go inside of each of these items is.
Now, the error would be to try to put a function right here. If we did that, then it would not be able to remember the values of the text as well as the ID. It would just loop to the last element and then show us only the last element always. So that's the trick that you have to remember when you're using a closure inside a loop. You have to create sort of a subclosure that allows you to get the elements properly.
Now, here's some pages where you can get more information about closures, and some related courses you may want to consider taking. If you have some ideas for this weekly series, maybe you want to share with me some questions you've been asked or have asked in interviews, connect with me via LinkedIn or in just about any other social media network like Twitter of GitHub at planetoftheweb.
Skill Level Intermediate
Q: Why can't I earn a Certificate of Completion for this course?
A: We publish a new tutorial or tutorials for this course on a regular basis. We are unable to offer a Certificate of Completion because it is an ever-evolving course that is not designed to be completed. Check back often for new movies.