The JavaScript You Don’t Know even goes so far as to say that “for those who have had a bit of JavaScript experience but never really understood the concept of closures, understanding closures can be seen as something of a rebirth”.
One of the most important precursors to understanding closures is scope and lexical scope. If you don’t understand lexical scope well, you can’t understand closures! So let’s get a better understanding of scope.
What is scope?
A scope is a set of rules for determining where and how to look for variables (identifiers). Finding variables (identifiers) is a key point to read in this sentence, so let’s start with finding variables.
function foo() { var a = 'ojbk' console.log(a); // output "ojbk"} foo()Copy the code
var a = 'ojbk' function foo() { console.log(a); // output "ojbk"} foo()Copy the code
Both pieces of code have look-up variables. The first piece of code finds variable A in the function, and the second piece of code finds variable B in the global, which leads to function scope and global scope
Code 2 looks in the function scope, doesn’t find it, looks in the global scope, and then looks in the outer scope. We seem to be looking for variables up a chain, which we call the scope chain.
Lookup rules for variables (identifiers) in scope
console.log(ojbs); Var ojbs= 'ojbk';Copy the code
console.log(ojbh); / / an errorCopy the code
AvaScript has a compilation process, not surprisingly, it does! Var ojbs= ‘ojbk’; This code actually has two actions:
- The compiler declares a variable ojbs in the current scope
- The runtime engine looks for the variable in scope, finds the OJBS variable and assigns it a value
What is a closure?
Closures are functions that can read variables inside other functions
function f1() {
var n = 1
function f2() {
console.log(n)
}
return f2
}
var f2= f1()
f2() // 1
Copy the code
In the above code, f2 can read the f1 function internal variable n, f2 is the closure
What are closures good for?
for (var i = 1; i <= 10; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
Copy the code
The code above prints 11 10 times
I is declared in the global scope. The anonymous function in the timer is also executed in the global scope. What if I want to print 1-10? Let I generate a private scope at each iteration that holds the current value of I.
for (var i = 1; i <= 10; i++) {
(function (j) {
setTimeout(function () {
console.log(j)
}, 1000)
})(i)
}
Copy the code
For (let I = 1; i <= 10; i++) { setTimeout(function () { console.log(i) }, 1000) }Copy the code
Practice is the mother of wisdom
function fun(n,o){ console.log(o); return { fun: function(m){ return fun(m,n); }}; } var a = fun(0); / /? a.fun(1); / /? a.fun(2); / /? a.fun(3); / /? var b = fun(0).fun(1).fun(2).fun(3); / /? var c = fun(0).fun(1); / /? c.fun(2); / /? c.fun(3); / /?Copy the code
The answer is in the comments