So, to talk through what’s happening here, I’m creating a variable called fruit and assigning it to a string ‘raspberry’, then I pass fruit to a function which creates and returns a function called logger which should log the fruit when called. When I call that function, I get a console.log output of ‘raspberry’ as expected.
But then I reassign fruit to ‘peach’ and call the logger again. But instead of getting a console.log of the new value of fruit, I get the old value of fruit!
I can side-step this by calling getLogger again to get a new logger:
But why can’t I just change the value of the variable and get the logger to log the latest value?
When getLogger is called, the logger function is created. It’s a brand new function. When a brand new function is created, it looks around for all the variables it has access to and “closes over” them to form what’s called a “closure”. This means that so long as this logger function exists, it will have access to the variables in its parent’s function and other module-level variables.
So what variables does logger have access to when it’s created? Looking at the example again, it’ll have access to fruit, getLogger, arg, and logger (itself). Read that list again, because it’s critical to why the code works the way it does. Did you notice something? Both fruit and arg are listed, even though they’re the exact same value!
Just because two variables are assigned the same value doesn’t mean they are the same variable. Here’s a simplified example of that concept:
Notice that even though we make b point to the value of variable a, we were able to change the variable a and the value b pointed to is unchanged. This is because we didn’t point b to a per se. We pointed b to the value a was pointing to at the time!
So then, when we later do fruit = ‘peach’, it has no impact on arg because they’re completely different variables.
Whether you think of this as a limitation or a feature, the fact is that this is the way it works. If you want to keep two variables up-to-date with each other, there is a way to do that! Well, sorta. The idea is this: instead of changing where the arrows (variables) point, you can change what they’re pointing to!
In this case, we’re not reassigning a, but rather changing the value that a is pointing to. And because b happens to be pointed at the same thing, they both get the update.
So, let’s apply this solution to our logger problem:
The Ref suffix is short for “reference” which is to say that the value the variable points to is simply used to reference another value (which in our case is the current property of an object).