Talk about the scope scope and closure closure in JS

Source: Internet
Author: User

Talk about the scope scope and closure closure in JS

Scope and closure are two very key concepts in JavaScript, the former JS with more than a good understanding, closure is not the same. I have been plagued by this concept for a long time, regardless of how others explain, it is not through. But the more the argument, the code written more, small program testing more, and then back to look at other people write the post, also gradually understand the meaning of closure. I am not a Daniel, so do not engage in so professional, the only idea is to try to let you understand what is the scope, what is the closure. If you have read this post you do not understand, so many months to write a code back to look, I believe you will have a harvest, if you see this post let you get some things, tell me, or very open Sen. Nonsense not much to say here we go!

1. function

Before we start, let's clarify a little bit (so much nonsense) that the function is a first-class citizen in JavaScript. What, you've heard it many times?!! What I need you to understand here is that a function can be invoked not only in JavaScript, but also as a value pass.

2. Scope and variable query

Scopes, which we often call lexical scopes, say that simple points are where your program stores variables, variable values, and functions.

  Block-level scopes

If you are exposed to block-level scopes, you should be very familiar with block-level scopes. To put it simply, the code enclosed in curly braces {} shares a scope, and the variables inside are visible at the block-level scope, either internally or inline.

  Function-based scopes

In JavaScript, scopes are defined based on functions. That is, the code that belongs to the inside of a function, both inside the function and inside the nested code, can access the variables of the function. As follows:

A function foo is defined above, and the function bar is nested inside it. The figure has three different colors, corresponding to three different scopes. ① corresponds to the global scope, where only Foo② is the scope of Foo definition, including, B, Bar③ is the scope of bar definition, here is only c this variable. When querying variables and manipulating them, the variables are queried from the current outward. In other words, ③ used a will query ③, ②, ① in turn. Because of a in the ②, so will not continue to check ①.

  Here, incidentally, two common Error,referenceerror and TypeError are spoken. For example, if D is used in bar, then the query ③, ②, ① are not found, then will be reported a referenceerror, if the bar used B, but there is no correct reference, such as B.ABC (), which will lead to TypeError.

Strictly speaking, there are also block-level scopes in JavaScript. Here are a few things:

①with

1 var obj = {a:2, b:2, C:2}; 2  with // are used on obj 3      A = 5; 4      b = 5; 5      c = 5;   6 }

②let

Let is a new method of defining a variable, and the variable defined by ES6 only exists within the nearest {}. As follows:

var true ; if (foo) {    = foo * 2;     = something (bar);     // Referenceerror

③const

As with let, the only difference is that the value of a const-defined variable cannot be modified. As follows:

1 varFoo =true;2 if(foo) {3     varA = 2;4Const B = 3;//only exists in the IF {}5A = 3;6b = 4;//error, value cannot be modified7 }8Console.log (a);//39Console.log (b);//referenceerror!

  

3, scope of how to determine

 Regardless of where the function is called, and regardless of how the function is called, its determined lexical scope is always determined when the function is declared. It is very important to understand this point.

4. Variable name Promotion

This is also a very important concept. Before understanding this concept, it is necessary to understand that the execution of JS code is divided into the process of compiling and executing. Examples are as follows:

1 var a = 2;

In fact, the above code will be divided into two processes, one is Var A;  One is a = 2; where Var A; is executed during the compilation process, a =2 is executed during execution. Understand this, then you should know why the following is the result:

1 Console.log (a);//undefined 2 var a = 2;

It performs the following effects:

1 var A; 2 Console.log (a); //undefined
3 a = 2;

We see that the variable declaration is advanced, which is why the variable name is promoted. So during the compile phase, the compiler will forward all declarations in the function to the upper part of the function body, and the actual assignment is left in the original position, which is why the code above undefined. It is important to note that the variable name promotion is bounded by the function, and the variable declared within the nested function does not ascend to the upper part of the outer function body. I hope you understand this concept, if you do not understand, you can refer to my previous written "also talk about the specification JS code several points of attention" and the comment answer section.

5. Closed Package

After this, let's talk about closures. What do you mean, closures? Simply put, a function is nested inside another function, which forms a closure. That might be more abstract, so let's give an example. But before the distance, we review this sentence, and then read it aloud, "no matter where the function is called, and no matter how the function is called, its deterministic lexical scope is always determined at the time the function is declared."

1 function foo () {2     var a = 2; 3     function Bar () {4         // 2 5     }6    Bar (); 7 }8 foo ();

We saw that the bar was nested in the function foo above, so bar formed a closure. You can access any variable within the bar that belongs to the scope of Foo. OK, let's take a look at the next example:

1 functionfoo () {2     varA = 2;3     functionBar () {4 Console.log (a);5     }6     returnBar;7 }8 varBaz =foo ();9Baz ();//2

In line 8th, after we execute foo (), the garbage collector releases the variables in the Foo lexical scope, but we still have access to the value of a in Foo when we run Baz (). This is because, although Foo () is done, it returns to bar and assigns a reference to the Baz,bar that still maintains the scope of Foo formation. This is why you can still access the value of a in Foo. Think again, our words, "no matter where the function is called, and no matter how the function is called, its deterministic lexical scope is always determined at the time the function is declared."

Here, let's look at a classic closure example:

1  for (var i=1; i<=9; i++) {2     function timer () {3    console.log (i); 4     },1000 ); 5 }

What's the result of running? You may expect to come out 1, 2, 3...10 every second. So try, press F12, open the console, paste the code, enter! Hey??? Wait a minute, wipe your eyes, how will it run 10 times 10 pinch? Is this a swollen thing? What's wrong with my eyes? Don't worry, wait for me to fool you!

Now, take a look at the above code, because settimeout is asynchronous, then in the real 1000ms before the end, actually 10 cycles are over. We can divide the code into two parts, one to deal with i++, and the other to handle the settimeout function. Then the above code is equivalent to the following:

1   //The first part of2i++;3    ... 4i++;//10 times in total.5 6    //a second section7SetTimeout (function() {8 Console.log (i);9}, 1000);Ten    ... OneSetTimeout (function() { A Console.log (i); -}, 1000);//10 times in total.

See here, I believe you have understood why the above is the result of the operation. Well, let's find out how to solve this problem and let it run as we expected!

Because the anonymous function in settimeout does not pass I as a parameter to fix the value of this variable, so that it remains, but directly refers to the external scope of I, so I change, also affect the anonymous function. Actually, it's going to be as simple as we'd expect it to be, you just need to define the settimeout function in a separate scope and pass me in. as follows:

1  for (var i=1; i<=9; i++) {2     (function() {3      var j = i; 4      function timer () {5          Console.log (j); 6      }, (+ ); 7     })(); 8 }

Do not be excited, brave to try, the result is certainly as you expected. Then look at an implementation scenario:

1  for (var i=1; i<=9; i++) {2     (function(j) {3         function  timer () {4             Console.log (j); 5         }, (+ ); 6     }) (i); 7 }

Ah, it's so simple, you must think so! So, look at a more elegant implementation scenario:

1  for ( let I=1; i<=9; i++) {2     function timer () {3        console.log (i); 4     }, (+ ); 5 }

Hey?! What about the swelling? Is not a mistake, do not worry, I also made a mistake here. This is because let needs to be executed in strict mode. Specifically how to use strict mode, Google it yourself!

6. Use

After so many withdrawals, you will say, this TM is nonsense Ah! Embarrassed, then the following will give you a useful example, also as the end of this article, but also as a study questions for you to see where the closure and the benefits.

1 functionPerson (name) {2     functionGetName () {3 Console.log (name);4     }5     return {6 Getname:getname7     };8 }9 varlittleming = Person ("Fool" );TenLittleming.getname ();

 

Ah, the code for a couple of hours of text, but also very tired Ah! Coincidentally you see this article, and coincidentally feel useful, praise a Bai! (Welcome to the sink!) )

Talk about the scope scope and closure closure in JS

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.