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:

  1. The compiler declares a variable ojbs in the current scope
  2. 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