JS detailed diagram of the scope chain and closure

Source: Internet
Author: User
Tags closure

JS detailed diagram of the scope chain and closure


Overcoming closure challenges


When I was a beginner of JavaScript, I was learning to close the bag and took a lot of detours. And this time back to the basic knowledge to comb, to clear the closure, is also a very big challenge.

How important is closures? If you are a friend on the front end, I have no way to visually tell you that closures are ubiquitous in real-world development, but I can tell you that front-end interviews, must-ask closures. Interviewers often use the knowledge of closures to determine the basic level of interviewers, conservative estimates, 10 front-end interviewers, at least 5 are dead on the closure.

Why, then, are closures so important, or are there so many people who don't understand them? Is it because people do not want to learn? Not really, but most of the Chinese articles that we find in our search for closures are not clearly explained by the closures. It's either a scratch or an enigmatic one, or simply a straight-up. Including myself once wrote a summary about closures, looking back, can't bear to look straight [face].

So the purpose of this article is to be able to clearly clear the closure of the package, so that the reader to see the master after the closure to the complete learning, rather than indefinitely.

I. Scope and SCOPE chain

Before I explain the scope chain in detail, you probably understand the following important concepts in JavaScript, by default. These concepts will be very helpful.

    • Underlying data types and reference data types
    • Memory space
    • Garbage collection mechanism
    • Execution context
    • Variable object and active object

If you do not yet understand, you can go to the first three articles in this series, there is a directory link at the end of this article. In order to explain the closure, I have done the basic knowledge for everyone to pave the ground. Haha, really good freshman play.

Scope

    • In JavaScript, we can define scopes as a set of rules that govern how the engine finds variables in the current scope and nested child scopes based on the name of the identifier.

      The identifier here refers to the variable name or function name

    • There are only global scopes and function scopes in JavaScript (because Eval is rarely used in our development, not discussed here).

    • The scope and execution context are two completely different concepts. I know a lot of people will confuse them, but be sure to make a careful distinction.

      The entire execution of JavaScript code is divided into two phases, the code compilation phase and the code execution phase. The compile phase is done by the compiler, which translates the code into executable code, which is determined by this phase of the scope rule. The execution phase is done by the engine, and the primary task is to execute the executable code, which is created at this stage.


Process

Scope chain

Review the life cycle of the execution context that we analyzed in the previous article, such as.


Execution context life cycle

We found that the scope chain was generated during the creation phase of the execution context. That's a strange thing. We just said that the scope determines the rules during the compile phase, but why is the scope chain determined at the execution stage?

All of this is problematic because there is a misunderstanding about scopes and scope chains. As we said above, scope is a set of rules, so what is the scope chain? is the concrete implementation of this set of rules. So this is the relationship between scope and scope chain, I believe everyone should understand it.

We know that when a function invokes activation, it begins to create the corresponding execution context, in which the variable object, scope chain, and the value of this are determined, respectively, during the execution of the context generation. In a previous article we explained the variable object in detail, and here we'll explain the scope chain in detail.

The scope chain, which consists of a series of variable objects in the current environment and the upper environment, guarantees an orderly access of the current execution environment to variables and functions that meet access rights.

To help you understand the scope chain, let's begin by combining an example with the corresponding diagram.

var a = 20;function test() { var b = a + 10; function innerTest() { var c = 10; return b + c; } return innerTest();}test();

In the example above, the global, function test, and function innertest are created in the execution context. We set their variable objects to VO (global), VO (test), VO (innertest), respectively. The scope chain of the Innertest also contains the three variable objects, so the execution context of the innertest can be represented as follows.

innerTestEC = {    VO: {...},  // 变量对象    scopeChain: [VO(innerTest), VO(test), VO(global)], // 作用域链 this: {}}

Yes, you have no mistake, we can directly use an array to represent the scope chain, the first item of the array scopechain[0] is the most front-end of the scope chain, and the last item of the array is the end of the scope chain, and all the ends are global variable objects.

Many people misunderstand the inclusion of the current scope and the upper scope, but it is not. From the front end to the end of the single-direction channel I think it is more appropriate to describe.


Scope Chain Diagram

Note that because the variable object becomes the active object when the execution context enters the execution stage, this is already mentioned in the previous article, so the figure uses AO to represent it. Active Object

Yes, the scope chain is made up of a series of variable objects, and we can query the identifier in the variable object in this one-way channel, so that we can access the variables in the previous level scope.

Second, closed package

For those who have a bit of JavaScript experience but never really understand the concept of closures, understanding closures can be seen as a rebirth in a sense, and breaking through the bottleneck of closures can make you more capable.

    • Closures are closely related to the scope chain;
    • Closures are confirmed during function execution.

A straightforward throw-out definition: When a function can remember and access the scope (except the global scope), a closure is generated, even if the function is executed outside the current scope.

Simply put, suppose function A is defined inside function B, and when function A is executed, it accesses the variable object inside function B, then B is a closure.

I am very sorry about the closure of the definition of the description of some inaccuracies, has now been changed, I hope the collection of the students can see the article again, I am sorry everyone.

In the basic step (i), I summarize the JavaScript garbage collection mechanism. JavaScript has an automatic garbage collection mechanism, and there's an important behavior about garbage collection, which is that when a value loses a reference in memory, the garbage collection mechanism finds it based on a particular algorithm and reclaims it to free up memory.

And we know that the execution context of the function, after execution, ends the life cycle, and the execution context of the function loses its reference. The memory space it occupies will soon be freed by the garbage collector. But the existence of closures will stop the process.

Let's start with a simple example.

var fn = null; function foo ( var a = 2; function innnerfoo ( console.log (a);} fn = Innnerfoo; //the reference to Innnerfoo, assigns the value to FN in the global variable} function bar ( //a reference to the reserved Innerfoo here}foo (); bar (); //2             

In the above example, foo() after execution, it is common sense that its execution environment life cycle will end and the occupied memory is freed by the garbage collector. However fn = innerFoo , the reference to the function Innerfoo is preserved and copied to the global variable FN. This behavior, which led to the variable object of Foo, was also preserved. Then, when the function FN executes inside the function bar, it can still access the preserved variable object. So you can still access the value of variable a at this point.

In this way, we can call Foo a closure.

Shows the scope chain of the closure FN.


The scope chain of the closure FN

We can view the generation of the function call stack and scope chain generated by this code when it is running in the developer tools of the Chrome browser. Such as.


As you can see, the Chrome browser thinks that the closure is Foo, not what we usually think of as Innerfoo

In the above figure, the Red Arrow refers to the closure. Where call stack is the current function calling stack, scope is the scope chain of the function currently being executed, and local is the current local variable.

So, with closures, we can access the internal variables of the function in other execution contexts. In the example above, we have access to the A variable of function foo in the execution environment of the function bar. Personally, from an application level, this is the most important feature of closures. Using this feature, we can achieve a lot of interesting things.

However, readers should note that although the closures in the example are stored in global variables, the scope chain of closures does not change. In closures, the variables that can be accessed are still variables that can be queried on the scope chain.

To make a slight change to the above example, if we declare a variable C in the function bar and try to access the variable in the closure FN, the result throws an error.

var fn =null; function foo ( var a = 2; function innnerfoo ( console.log (c); //here, trying to access the C variable in the function bar, throws an error console.log (a);} fn = Innnerfoo; //the reference to Innnerfoo, assigns the value to FN in the global variable} function bar ( var C = 100; FN (); //a reference to the reserved Innerfoo here}foo (); bar ();           

Closure application Scenarios

Next, let's summarize the common scenarios for closures.

    • Delay function settimeout

We know that the first parameter of settimeout is a function, and the second parameter is the time of delay. In the following example,

function fn() {    console.log(‘this is test.‘)}var timer = setTimeout(fn, 1000);console.log(timer);

Executing the above code, the value of the variable timer will be output immediately, indicating that the settimeout function itself has been executed. However, after a second, FN will not be executed. Why is this?

In the sense that since FN was passed into the settimeout as a parameter, FN will be saved in the SetTimeout variable object, and after the execution of the settimeout, its variable object will not exist. But that's not the truth. At least in this one-second event, it's still there. This is precisely because of closures.

Obviously, this is in the internal implementation of the function, and settimeout retains the FN reference in a special way, letting the settimeout variable object not be reclaimed by the garbage collector after it has finished executing. So we can execute the FN function one second after settimeout execution.

    • Currying

In functional programming, the use of closures to achieve a lot of cool features, currying is considered one of them. As for the curry, I'll summarize it later in the detailed functional programming.

    • Module

In my opinion, the module is one of the most powerful application scenarios for closures. If you are a beginner, the understanding of modules can be a temporary no-no, because understanding the module requires more basic knowledge. But if you already have a lot of javascript experience, after a thorough understanding of the closure, you may want to use the scope chain and closures described in this article to rethink the knowledge of the module. This is very helpful for us to understand the various design patterns.

 (function (var a =  10; var B = 20; function add ( num1, num2) {var NUM1 =!! Num1? num1:a; var num2 =!! Num2? Num2:b; return num1 + num2;} window.add = add;}) (); Add (10, 20);        

In the example above, I created a module using the self-executing method of the function. Method add is used as a closure, exposing a public method to the outside. The variable A, a, is used as a private variable. In object-oriented development, we often need to consider whether a variable is a private variable or the This in the constructor, so understanding closures and prototype chains is a very important thing. Module is very important, so I will be in a future article specifically introduced, here is not much to say.


In this diagram, you can view the call stack and scope chain of the current code execution to the Add method, and the closure is the self-executing function of the outer layer at the moment.

In order to verify that they do not understand the scope chain and closure, here is a classic study questions, often will be asked in the interview.

Using closures, modify the following code so that the results of the loop output are 1, 2, 3, 4, 5

for (var i=1; i<=5; i++) {     setTimeout( function timer() { console.log(i); }, i*1000 );}

JS detailed diagram of the scope chain and closure

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.