I have 2 question
What is the difference between counter1()
and counter1()()
?
Isn't counter1 already the function name? Why the second ()
?
Why counter2 can memorize the value?
Here is my code:
const counter1 = function(){
let initValue = 0
return function(){
initValue++;
return initValue
}
}
const counter2 = (function(){
let initValue = 0
return function(){
initValue++;
return initValue
}
})()
console.log(counter1());
console.log(counter1()());
console.log(counter1()());
console.log(counter2());
console.log(counter2());
Here is the output:
counter1
is a function that returns a function, or what is called a higher-order function.
For the ease of discussion, let innerCounter1
be the name of the return value of counter1
. So the following code is equivalent to what you have in your example.
const counter1 = function(){
let initValue = 0
const innerCounter1 = function(){
initValue++;
return initValue
}
return innerCounter1;
}
Isn't counter1 already the function name? Why the second ()?
Yes, counter1
is a function, but it also returns a function. By naming the return value innerCounter1
, I hope it's clear that when you call counter1()
, the value you get is innerCounter1
. And when you call innerCounter1()
, the value you get is the number initValue
. So counter1()()
is getting the value of innerCounter1
and calling that inner function in one short expression.
Why counter2 can memorize the value?
When a function is created (innerCounter1
in your example), and the function references value defined outside of the function (initValue
in your example), a closure is created, which you can intuitively understand as "memorizing" the variable. Both the functions counter1()
and counter2
remembers the value, but the thing to note here is that each time counter1()
is called, the local variables (initValue
and innerCounter1
) are independent. For example:
let counter1A = counter1();
let counter1B = counter1();
counter1A(); // 1
counter1A(); // 2
counter1B(); // 1
counter1B(); // 2
In other words, counter1A
and counter1B
are remembering a separate initValue
variable, so calling one doesn't affect the other.
And this definition of counter2
: let counter2 = counter1();
, is equivalent to yours above with the anonymous function syntax, so it should be clear that what's happening is exactly the same as counter1A
I explained above.