JavaScript Pass By Value Function Parameters
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?
The answer is the fact that in JavaScript, when you call a function with arguments, the arguments you’re passing are passed by value, not by reference. Let me briefly describe what’s going on here:
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!
I like to think of variables as little arrows that point to places in the computer’s memory. So when we say let a = 1, we’re saying: “Hey JavaScript engine, I want you to create a place in memory with the value of 1 and then create an arrow (variable) called a that points to that place in memory.”
when we say: let b = a, we’re saying “Hey JavaScript engine, I want you to create an arrow (variable) called b that points to the same place that a points to at the moment.”
In the same way, when you call a function, the JavaScript engine creates a new variable for the function arguments. In our case, we called getLogger(fruit) and the JavaScript engine basically did this:
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!
For example:
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).