- [Tutor] Even though the ability to return a closure
can be helpful in code organization,
this feature of JavaScript wouldn't necessarily
be very powerful if a function could return
only a single reference.
If I wanted to reuse the same function
elsewhere in my application,
but had all of my uses referencing
the same closed over values,
my code would quickly become redundant
and harder to maintain.
Fortunately, this is not how closures work.
In fact, one of the super powers of a function
that creates a closure is that it can create references
to multiple closed over variables
that are independent of each other.
Let's explore this in our code.
We have a function that creates a closure
to log clicks on the buttons at the top of the app.
But how about if we want to reuse this function
to also log each time a user moved the mouse
over one of the items in the product gallery
further down the page?
So in the browser,
scrolling down to the products section
and let's dig into one of those gallery elements.
I'm going to right click here and click inspect.
And so notice that these items do not have ID values
like the buttons do.
And this means we're going to have to abstract out
our code a little bit
so we can instead pass in values that aren't ID values.
So first off, we'll replace the parameter name menu
with a more generic name and we'll use item.
And then we'll take out that button variable
and we'll take out the code that sets the value
of the button variable as well.
And then we'll change all three references
from button to reference the item parameter instead.
So here it's going to be clicks item,
here it's going to be clicks item
and here we're going to reference item, comma clicks.
And then instead of creating a simple report function
down in line 12,
we want to create two distinct report functions,
one for the activities buttons,
and another for the product gallery.
So I'll rename that existing variable to report activities,
and then we'll create another statement using const
to create a variable called report products
and set its value to update clicks as well.
So now I'll have two functions whose values
are both equal to the report clicks function
that's returned from calling update clicks.
And then scrolling down to the bottom of the file,
we need to update the event listener
for the activity buttons.
First, we need to change the reference
to the report function
to call the report activities function instead.
And we need to pass
the ID value of the element that was clicked.
So instead of event.target,
we're going to use event.target.id.
Now we also want to create an event listener
for the items in the product gallery.
They don't currently have an event listener
because their visual effects are created with pure CSS.
So, we'll add a document dot query selector all
and we'll select .productimage.
And then we'll use for each adding function
and grabbing that element
so that we can add an event listener
to each one of those elements.
So el.addeventlistener,
we're going to listen for the mouse enter event,
and we're going to specify an anonymous function,
also captures an event
and we'll use this anonymous function
to call our second new function report products.
And here we want to pass in the text of the H three element,
that's a sibling of the image
that we're binding the event to.
And we can get that by grabbing the event object,
and using the target property,
specifying the next elementsibling.textcontent.
And then on the next line,
just adding that final parameter false,
adding our semi-colon there on line 117.
So this is going to pass a unique text string
that identifies the gallery item
that the mouse has just entered.
And then scrolling up to lines 12 and 13,
we might think that because we're getting two references
to the same variables, we're going to get one big object
that's got all our data mixed up in it,
which is not what we want,
but it turns out that's not how closures work.
So we'll save our work,
we'll reload in the browser,
and I'll enter Boston and we'll test our activities,
and so far so good.
We get the same object in log statements that we're used to.
And then scrolling down to the gallery,
I'll just start moving the mouse around
and notice I have an object being logged,
showing the text of these different headers,
but I don't see anything that references the buttons above.
And then moving back up to the top
and clicking the buttons again,
and the object being displayed here,
doesn't contain any of the gallery headings.
So we have references to two entirely different variables.
And so closures enable us to create
not just a single set of private variables,
but as many distinct references to copies
of those private variables as we want.
And this means we can keep our code dry
using a single function
to return as many references as we need
to reuse the same code within an app.