What is a closure?
Let’s put it this way: a combination of a function bundled with references to its surrounding state (lexical environment) is a closure.
How does each recognize the word combination together to see not to understand 🤣?
Before you get confused, consider the output of the following code:
function sayHello() {
var sentence = "Hello,world!";
function say() {
console.log(sentence);
}
say();
}
sayHello();
Copy the code
Obviously, the output of the code is: Hello,world! . You can sort out the process:
- perform
sayHello
methods(sayHello (); - Define variables
var sentence = "Hello,world!"
And,sentence
The scope of a variable is limited tosayHello
The sayHello method is not externally accessible.Var sentence = “Hello,world!” 😉 - call
sayHello
Internal methodssay
Methods.(say); - because
say
Method is defined assayHello
Internal, so it can undoubtedly be accessed to the same definition insayHello
Variables in methodssentence
. There seems to be nothing wrong with the code.
But this?
function sayHello() {
var sentence = "Hello,world!";
function say() {
console.log(sentence);
}
return say;
}
var fun = sayHello();
fun();
Copy the code
We might think of the process as:
- call
sayHello
Methods and methodsfun
The variable holds its return value.Var fun = sayHello(); sayHello
Is a function object:say
(return say;). So we can call it externallysay
Methods.(fun ();)- Enter the
say
Setsentence (); setsentence ()(the console log (sentence);Where is sentencevar sentence = "Hello,world!" ;
This. But sayHello is done,sentence
How can a variable still exist?
Therefore, sentence is undefined? Instead, the output is still: Hello,world! .
How could this be! In this case, we can only assume that the sayHello method instance say is not simply a function, and that it must somehow hold the sentence variable so that it can be accessed when executed.
Originally, functions in JavaScript form closures. Closures are a combination of functions and the lexical environment in which they are declared. The environment contains any local variables that were in scope when the closure was created.
As we expected! :
Say is the internal sayHello method. When we get an instance of the say method (var fun = sayHello()), the say instance ensures that all of its internal variables are properly accessed. Therefore, it is not surprising that when we call fun, an instance of say, we can access the variable sentence used by say.
Bad and good…
Closures look strange, as you might expect if every time a function instance is created, its internal methods have to be redefined.
Take the constructor as an example:
function Person(name,age) {
this.name = name;
this.sayHello = function(){console.log("My name is ",name)};
}
Copy the code
According to closures, sayHello is defined repeatedly each time a Person is instantiated. If there are a lot of instance objects, repeating methods can take up a lot of space. Fortunately, prototypes can be used here:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function(){console.log("My name is ".this.name)};
Copy the code
So what’s good about closures? Of course, closures have their advantages.
Closures bind external variables and method instances together. Is this an encapsulation?
We can:
var names = ["chao"."zhao"."tao"."yao"];
var say = function(str){
return function(){
console.log("My name is ",str);
};
};
var funs =[];
for(var i in names)
funs[i] = say(names[i]);
for(var f of funs)
f();
Copy the code
The internal method of SAY maintains its own lexical environment, holding the variable STR. So, although STR is constantly changing (each STR is a new STR), the method instances are maintained one by one, so the output of each method instance in the array funs is ultimately called is different:
My name is chao
My name is zhao
My name is tao
My name is yao
Copy the code
👌, probably so, each big guy reward a praise 👍 bie!
— — — — — —
One last example if you don’t use an inner function:
var names = ["chao"."zhao"."tao"."yao"];
var say = function(str){
console.log("My name is ",str);
};
var funs =[];
for(var i in names)
funs[i] = function(){console.log("My name is "+names[i])};
for(var f of funs)
f();
Copy the code
Output:
My name is yao
My name is yao
My name is yao
My name is yao
Copy the code
This is because functions maintain the lexical context of each closure, but I remains the same. Keep going, keep going, always the I that ends up equal to 3 (if I use for(var I = 0; i < names.Length; I ++) and finally I is 4). Let I instead of var I is different, the reason can be explained by 😆.