This works similarly to the previous example where message
was remembered. However this example demonstrates that functions can also change the variable that is remembered. When counterFuncA
is called three times, the value of the counter
variable that it remembered is incremented, causing it to return an incrementing value.
The variable that is remembered is also unique to each function returned. Notice how calling counterFuncB
returns 0 again. That's because it has its own copy of the counter
variable that is incremented independently. In other words, each function returned by makeCounterFunction
remembers its own separate copy of the counter
variable, and can modify it independently.
It's also worth pointing out how the code outside makeCounterFunction
has no way to modify the counter
variable, as it's outside the variable's scope, so you can't write code that references it there. However the returned functions are bundled with the variable and can still use it in their function bodies. This provides a form of encapsulation: the counter
variable is private to the returned function, as it's impossible to modify it by any means other than calling the returned function. For example it's impossible to write code that resets counter
back to 0: the only way to support that would be if makeCounterFunction
returned something different that specifically allowed that.
The full technical details about how closures work is quite an advanced topic, so we won't cover any more about closures here. However it's an important feature of JavaScript's functions that is useful to be aware of. In summary, JavaScript functions can hold on to things outside their scope, and keep using them after they would otherwise have stopped existing. Try experimenting with more examples to help improve your understanding. If this seems complicated, don't worry too much - it won't come up much more in the rest of the guide, and you can always revisit it later on. This section aims to just introduce you to the concept, so you at least know it's possible to do this.
Conclusion
In this part we've covered more about functions:
- Function expressions, and how functions can be used like any other data type, such as numbers and strings
- Passing functions as parameters to other functions (aka "callbacks")
- Returning functions from functions
- Recursion
- Arrow functions as a shorter way of writing function expressions
- An introduction to closures
There is even more to functions in JavaScript - we could write an entire guide on functions alone! However we've covered most of the key features of functions that are relevant to beginners, and so it's time to move on to the next topic. In the next part of this guide we'll move on to objects.
Learn more
If you want to dig deeper, you can learn more about the features mentioned in this guide at the following MDN Web Docs links:
Part 7
When you're ready to continue, head on to the next part at Learn JavaScript in Construct, part 7: Objects!