In the previous article, we gave an overview of the pre-explanation. Before writing this blog post, we planned to write a few classic cases. Considering that those cases are more comprehensive, we have this blog post step by step, which is easier to learn and in-depth JavaScript.
sequence
A colleague went to the interview and the interviewer asked a question: Do you write a closure and I'll read it? So my colleague quickly wrote the following code:
The code copy is as follows:
function fn(){
alert('Hello JavaScript Closure!!!');//Damn it, E text is not good, you can only write the closure words after finding a translation
}
fn();
Then the interviewer shook his head and said, "How can this be called a closure?" In the end, the two of them had a dispute, and the colleague left decisively. What's the interviewer's thing? (This story is purely fictional, if there is any similarity, it is purely coincidence)
Closures may be "high-end and difficult" technology in many people's eyes, but in many people's eyes, they may be considered closures:
Example 1:
The code copy is as follows:
function fn() {
return function () {
alert('Example 1');
}
}
fn()();
Example 1 PS: This one doesn’t look very advanced, it seems that this person is not very good at it!
Example 2:
The code copy is as follows:
;(function () {
alert('Example 2');
})();
Example 2 PS: This looks more advanced than the previous one, and there is a semicolon before the first bracket. Why add a semicolon? Well, let's leave this question here first, and we will talk about it later.
Example 3:
The code copy is as follows:
~function fn() {
alert('Example 3')
}();
Example 3 PS: This is the most advanced, it’s so amazing. I read less, don’t lie to me!
The master of Lun is not reading much, and he can only write these three "closures". I believe that bloggers can write more and better "closures"; here, please pause my nonsense first, and then study the mechanism of function operation. It seems that someone already knows it, it must be the scope. I really don't want to add this scope to the title, so I always feel that it is almost meaningful. These things are originally together, so why should I repeat them? Old habit, first upload the code:
The code copy is as follows:
var n = 10;
function fn(){
alert(n);
var n = 9;
alert(n);
}
fn();
To put it simply, we draw pictures (the master only uses the drawing software that comes with Windows. If there are any better ones, please recommend it to bloggers) to analyze it:
Analysis 1
From the figure, we see two scopes, one is the window scope (top-level scope), and the other is a private scope formed when fn is called; then what is scope? The scope is actually the environment for code execution. For example, a student's learning environment is a school, which is equivalent to his scope. If the student is naughty and often goes to the Internet cafe to play games at night, it is equivalent to forming a private environment, which is an Internet cafe. All right! This Lizi is so till she looks like the master himself, and she can't help but sigh: "If you don't work hard when you are young, you will be kicked when you grow up." Let's go back to the topic. In fact, the definition of the function fn refers to the description of a piece of code (the red box in the figure). When this fn is called (the green box in the figure), a scope will be formed. Of course, the code in this scope will also be pre-explanated before execution. I will not tell you that this scope will be destroyed after execution. This fn is called again, and it will also form a new scope, and then pre-explanated before execution, then code execution, and finally destroyed after execution.
Understand closures
We know that when a function is called, a private scope (execution environment) will form a private scope (execution environment), and this private scope is a closure. Looking back, is the closure still the legendary "high-end and not easy to get on"? Let’s look back at the first interview story, and the three examples I wrote, they are actually closures. To be precise, those three examples are common forms of closures.
Application scenarios
Now there is a requirement: there is an ul tag in the HTML page, and there are 5 li tags under ul. You require any click on a li, and the index (index starts from 0) where the clicked li is popped up. The HTML structure is as follows:
The code copy is as follows:
<ul id="ul">
<li>List 1</li>
<li>List 2</li>
<li>List 3</li>
<li>List 4</li>
<li>List 5</li>
</ul>
I was smart and quickly wrote the following code:
The code copy is as follows:
var lis = document.getElementById('ul').getElementsByTagName('li');
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].onclick = function () {
alert(i);
};
}
Final test to see if this requirement is perfectly implemented:
I found that no matter how many times I clicked, this result will pop up in the end. The desired result is: Click List 1 to pop up 0, click List 2 to pop up 1, click List 3 to pop up 2... At this moment, I just want to use this picture to describe my current mood:
(What does it look like when the prototype fails to run as the design requirements during demonstration)
What should I do? Why does 5 always pop up? It's very correct in theory! Let's draw a picture to analyze:
In fact, we just give each li onclick, which is actually a function description string that saves. The content of this string is the content in the red box of the picture above. If you still don't believe it, I have the picture and the truth:
Enter: lis[4].onclick in the Chrome console, and its value is the description of the function. When we click on the fifth list, it is actually equivalent to lis[4].onclick(). After calling this function description, we know that when the function is executed, it will form a private scope. In this private scope, it will be pre-explained first, and then the code will be executed. At this time, we will look for i. There is no i under the current private scope, and then find i under the window scope, so 5 pops up every time you click.
Obviously, the above code cannot meet this requirement. It is incorrect to write our code. Let’s think about the reasons for the problem? In fact, the reason is that every time I click, it is read in the i under window. At this time, the value of this i is already 5, so the following code is available:
Method 1:
The code copy is as follows:
var lis = document.getElementById('ul').getElementsByTagName('li');
function fn(i) {
return function () {
alert(i);
}
}
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].onclick = fn(i);
}
Method 2:
The code copy is as follows:
var lis = document.getElementById('ul').getElementsByTagName('li');
for (var i = 0, len = lis.length; i < len; i++) {
;(function (i) {
lis[i].onclick = function () {
alert(i);
};
})(i);
}
Method 3:
The code copy is as follows:
var lis = document.getElementById('ul').getElementsByTagName('li');
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].onclick = function fn(i) {
return function () {
alert(i);
}
}(i);
}
I wrote three methods in one breath, and the ideas are the same, which is to store this variable i in a private variable. Here I will only talk about method two. Of course, if you understand one of them, you will understand the rest. According to convention, let’s draw a picture and analyze it step by step:
I have described the entire code execution in detail. It should be noted that the onclick attribute of each li must occupy the (function(i){ … })(i) scope. When this function is executed, it will not be destroyed because it is occupied by the external li (this li is under the window scope), so this scope will not be destroyed. When clicking on any li, function(){ alert(i); } will be executed and a scope will also form. This scope does not have i. It will go to (function(){ … })(i) scope to find i, and finally find i in the formal parameter, and the value of this formal parameter is passed in during the for loop; this example cleverly uses closures to store the value, perfectly solving the problem.
PS: I just said (function(i){ … })(i) why I added a semicolon in front of it is to prevent the previous statement from forgetting to add a semicolon, which causes JavaScript to make errors during parsing, and that's all. Of course, one of the above application scenarios is the Tabs implementation principle. There can be other implementation methods, such as custom attribute methods and finding indexes through DOM node relationships. The master adopts this method just to deepen his understanding of closures.
Summarize
Closures are not as tall as the legendary ones. The core is to understand function definitions and calls. A new private scope will be formed when a function is called. When a scope is occupied by outside, the scope will not be destroyed. The Master of Lu reads very little. If there are any wrong things, please correct me by bloggers. At the same time, I would like to thank you for your support for the Master of Luke’s article.