Before we start talking about closures, we need to take a look at scope and lexical scope, for example, scope, lexical scope, scope Chain, lexical Environment, and Execution Context
Closure (Closure)
Lexical scope allows us to statically access variables in outer scope
function outerFunc() {
// --- start lexical scope
let outerVar = 'I am outside! ';
// start closure
function innerFunc() {
console.log(outerVar); // => logs "I am outside!"
}
// end closure
return innerFunc;
// --- end lexical scope
}
const myInnerFunc = outerFunc();
myInnerFunc();
Copy the code
MyInnerFunc () still prints ‘I am outside! ‘, here are some important points:
- Although innerFunc is executed outside of its lexical scope, it can still access the variable outerVar in the Outer scope
- In other words, innerFunc() captures the variable outerVar defined in outerFunc() from its lexical scope (an important feature of closures)
Conclusion:
A closure is a function that can access its lexical scope even if the function is executed outside of its lexical scope. In other words, a closure is a function that remembers (or captures) variables from where they were defined, even if the function is executed outside its lexical scope
Application scenarios for closures
Event handler
let countClicked = 0;
myButton.addEventListener('click'.function handleClick() {
countClicked++;
myText.innerText = `You clicked ${countClicked} times`;
});
Copy the code
Callback
Case 1:
const message = 'Hello, World! ';
setTimeout(function callback() {
console.log(message); // logs "Hello, World!"
}, 1000);
Copy the code
Example 2:
let countEven = 0;
const items = [1.5.100.10];
items.forEach(function iterator(number) {
if (number % 2= = =0) { countEven++; }}); countEven;/ / = > 2
Copy the code
Functional Programming
function multiply(a) {
return function executeMultiply(b) {
returna * b; }}const double = multiply(2);
double(3); / / = > 6
double(5); / / = > 10
const triple = multiply(3);
triple(4); / / = > 12
Copy the code
stale closure
function createIncrement(incBy) {
let value = 0;
function increment() {
value += incBy;
console.log(value);
}
const message = `Current value is ${value}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement(1);
increment(); // logs 1
increment(); // logs 2
increment(); // logs 3
// Does not work!
log(); // logs "Current value is 0"
Copy the code
Log () increments Current value is 0, increment value = 3, log() increments Current value is 0.
Since log() is a stale closure, its value is outdated(0), so no matter how many times increment() is executed, it prints 0
How to fix this problem?
function log() {
const message = `Current value is ${value}`;
console.log(message)
}
Copy the code
As shown above, you simply retrieve the value of value every time you call log()
Stale Closure: this closure captures a outdated value
reference
- simple-explanation-of-javascript-closures/
- react hooks stale closures
- JavaScript you Don’t Know, vol. 1