I'm learning javascript by reading "Eloquent Javascript" and am confused by the "Closures" section in chapter 3 (Functions).
In previous sections I learned about arrow functions, and how they can be used as anonymous functions. My initial thoughts were that this is an anonymous function example and I am simply not familiar yet.
In particular, I am confused on what "() => local" does to/for return.
function wrapValue(n) {
let local = n;
return () => local;
}
let wrap1 = wrapValue(1);
let wrap2 = wrapValue(2);
console.log(wrap1());
// → 1
console.log(wrap2());
// → 2
Here is a link to the chapter: Eloquent Javascript - Ch. 3 "Functions"
Thanks in advance!
In javascript function create scope. For example:
function scoped(){
let local = 10;
console.log(local) // this works local is within scope
}
scoped() // logs:
console.log(local) // error -- local doesn't exist out here.
Outside of scoped
local
doesn't exist.
A function inside a function has access to the entire scope. So this works:
function scoped() {
let local = 10;
function f() {
console.log(local) // this works local is within scope
}
f()
}
scoped()
But what happens if you return that function that references the scope of the function? It turns out that the inner function carries the whole scope with it. This is a closure:
function scoped(){
let local = 10;
function f(){
console.log(local) // this works local is within scope
}
return f
}
f = scoped()
f() // can still see local
// but nobody else out here can:
console.log(local) // still an error
This allows you to do some very slick things — an import one is that you can keep certain variables private, but still manipulate them with the closure.
For example here's a counter that doesn't require a variable in global scope:
function counter(){
let count = 0
return () => count++
}
let c = counter()
console.log(c()) // it can count but there's not count variable in scape
console.log(c())
console.log(c())
Doing this with a global count variable is messy and risks some other part of the code clashing with the global variable. Above, nothing other than the c
function can access the counter. In fact you can make several independent ones:
function counter(){
let count = 0
return () => count++
}
let c = counter()
let d = counter()
console.log("c:", c()) // it can count but there's not count variable in scape
console.log("c:", c())
console.log("d:", d()) // d has it's own closure
console.log("d:", d())
console.log("c:", c())
There's a lot you can do with closures and they're important in Javascript. It's worth taking the time to really understand them.
function wrapValue(n) {
let local = n;
return () => local;
}
Is the same as writing (without the benefits of "this")
function wrapValue(n) {
let local = n;
return function() {
return local;
}
}
It's a function that returns another function that uses the passed parameters. This is called a Curry function
console.log(typeof wrapValue(2)); // prints "function"
console.log(wrapValue(2)()); // prints "2"
Here's a better example
function multiple(a) {
return (b) => a*b;
}
console.log([1,2,3,4].map(multiple(2)); // prints "[2,4,6,8]"
You can use curried functions very easily with Arrays
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With