Understanding of closures in JavaScript

Source: Internet
Author: User
Tags closure

Closure in front-end development is a very important point of knowledge, is the content that will be asked in the interview. Before my understanding of closures is mainly "through the closure can be outside the function can access the variables inside the function," the closure of the use of very little, and even write their own closures themselves are not very clear, only know that this can solve the problem. Recently in combing their own JS knowledge points, found that their understanding of JS closure is very not thorough, so want to comprehensively analyze the closure, especially the cause of closure and the use of closure scenarios.

Definition of closures

Closures are functions that have access to variables in another function scope-JavaScript advanced programming

function objects can be associated by scope, variables within the function body can be stored in the function scope, which is called "Closure" in computer science literature, all JAVASCIRPT functions are closures-the JavaScript authoritative guide

After reading these professional definitions is not feeling confused, it's okay, I do not understand the same as the definition of what is said, we continue to analyze.

Before we know the theory of closures, we must first have a thorough understanding of scopes, execution contexts, execution context stacks, variable objects, active objects, scope chains

Scope scope

Scopes are a set of rules that determine where and how to find variables (identifiers)
There are two main types of work models in scope:

    • Lexical scopes: Scopes are determined at the time of writing code
    • Dynamic scope: The scope is determined when the code is run

We know that JavaScript uses lexical scopes

Execution context Execution contexts

The execution context of code in JavaScript is divided into the following three types:

    • Global level Code – this is the default code runtime environment, and once the code is loaded, the engine first enters the environment.
    • Code at the function level – when executing a function, run the code in the body of the function.
    • Eval Code – code that runs within the Eval function.

The context of an execution can be abstracted as an object. Each execution context has a series of attributes (variable object (variable objects), this pointer (this value), scope chain (scope chain))

Execution Contexts = {    variable object:变量对象;    this value: this指针;    scope chain:作用域链;}
Execution context stack execution contexts stack

The active execution context group logically composes a stack. The bottom of the stack is always the global context (Globalcontext), and the top is the current (active) execution context.

<script>functionadd(num){    var=5;    return+ num;}var=add(4);</script>

When the Add function is called, the Add function execution context is pressed into the top of the execution context stack, at which point the execution context stack can be represented as:

EC Stack = [  <add> functionContext  globalContext];

When the Add function finishes executing, its execution context pops up from the top of the execution context stack and is destroyed. The global execution context is destroyed from the execution context stack only when the browser is closed

Variable Objects Variable Object

If the variable is related to the execution context, the variable should know where its data is stored and know how to access it. This mechanism is known as a variable object (variable objects).
It can be said that the variable object is the scope of data that is related to the execution context. It is a special object associated with the execution context that stores variables (variables), function declarations (functions declarations) that are defined in the execution context.
When entering the global context, a variable object of the global context can be represented as:

VO = {    add: <reference to function>,    sum: undefined,    Math: <...>,    String: <...>    ...    window: global //引用自身}
Active Objects Activation Object

This special active object (activation object) is created when the function is activated by the caller. It contains common parameters (formal parameters) and special parameter (arguments) objects (parameter mapping tables with indexed properties). The active object is used as a variable object in the context of the function.
When the Add function is called, the Add function execution context is pressed into the top of the execution context stack, and the active object in the Add function execution context can be represented as

AO = {    num: 4,    sum :5,    arguments:{0:4}}
Scope Chain Scope Chain

The scope chain of a function context is created when the function is called, containing the active object AO and the [[scope]] property inside the function.

var  x =  10   function  foo  () { var  y =  20   Span class= "OP";  function  bar  () { var  z =  30     Span class= "OP";  alert  (X +  y +  z)   }  bar  ()  }  foo  ()   

In this code we see that the variable "y" is defined in the function "foo" (meaning it is in the AO of the foo context) "Z" is defined in the function "bar", but the variable "x" is not defined in the "bar" context and, accordingly, it is not added to the AO of "bar". At first glance, the variable "x" does not exist at all with respect to the function "bar";
How does the function "bar" access the variable "x"? Theoretically, a function should be able to access a variable object of a higher level of context. It is, in fact, a mechanism that is implemented through the [[scope]] property within the function.
[[Scope]] is a hierarchical chain of all parent variable objects, above the current function context, and stored in the function when it is created.

Note: [scope] is stored at the time the function is created (unchanged) until the function is destroyed. That is, the function can never be called, but the [scope] property has been written and stored in the function object.
Here we step into the analysis
The variable object for the global context is:

globalContext.VO === Global = {  x: 10  foo: <reference to function>};

When "foo" is created, the [scope] property of "foo" is:

foo.[[Scope]] = [  globalContext.VO];

When "foo" is activated (into context), the active object of the "foo" context is:

fooContext.AO = {  y: 20,  bar: <reference to function>};

The scope chain for the "foo" context is:

fooContext.Scope = [  fooContext.AO,  globalContext.VO];

When the inner function "bar" is created, its [[scope]] is:

bar.[[Scope]] = [  fooContext.AO,  globalContext.VO];

When "Bar" is activated, the active object in the "bar" context is:

barContext.AO = {  z: 30};

The scope chain for the "bar" context is:

bar.Scope= [  barContext.AO,  fooContext.AO,  globalContext.VO];

Introduced a lot of content, is not a bit dizzy flowing away quickly? Hold on, here's the point.

The principle of closure

We analyze how closures are formed by using a closure example.

functionadd(){    var=5;    var=function{        console.log(sum);    }    return func;}var=add();addFunc();//5

When the JS execution stream enters the global execution context, the global execution context can be represented as:

globalContext = {    VO: {        add: <reference to function>,        addFunc: undefined    },    this: window,    scope chain: window }

When the Add function is called, the Add function execution context can be represented as:

addContext = {    AO: {        sum: undefined //代码进入执行阶段时此处被赋值为5        func: undefined //代码进入执行阶段时此处被赋值为function (){console.log(sum);}    },    this: window,    scope chain: addContext.AO + globalContext.VO }

After the Add function is executed, the JS execution stream goes back to the global context and assigns the return value of the Add function to Addfunc.

Since Addfunc still holds a reference to the Func function, the Add function execution context pops up from the top of the execution context stack and is not destroyed but is saved in memory.

When Addfunc () executes, the Func function is called, at which point the Func function execution context can be represented as:

funcContext = {    this: window,    scope chain: addContext.AO + globalContext.VO }

When the variable sum is to be accessed, the Func's active object is not found, then it is located along the scope chain, because JS follows the lexical scope, the scope is determined during the function creation phase, and the sum = 5 is found in the active object of the Add function;

Introduction to Here do you understand the reason for the closure?
JavaScript allows the use of intrinsic functions---that is, function definitions and function expressions in the function body of another function. Furthermore, these intrinsic functions can access all local variables, arguments, and other intrinsics declared in the outer function in which they are located. When one of these intrinsics is called outside the outer function that contains them, a closure is formed.

Use of closures

Closures can be used in many places. Its maximum usefulness is two, one of the previously mentioned variables that can read the inside of a function, and the other is to keep the values of these variables in memory at all times.

1. Secure implementation of protection variables JS private properties and Private methods

The variables inside the function can be read by the closure, and the variables cannot be read directly outside the function to achieve the security of the protection variables. Because private methods can be accessed inside the function, the private properties and methods are shared.
A common module pattern is the use of closures to create

varCounter=(function(){  //Private Property  varPrivatecounter= 0;   //Private method  function Changeby(Val){Privatecounter+=Val;  }  return {    Increment: function(){      Changeby(1);    },    Decrement: function(){      Changeby(-1);    },    value: function(){      returnPrivatecounter;    }  }   })();Console.Log(Privatecounter); //privatecounter is not definedConsole.Log(Counter.value()); //0Counter.Increment();Counter.Increment();Console.Log(Counter.value()); //2Counter.Decrement();Console.Log(Counter.value()); //1

Private methods and variables in the jquery framework are also designed

var$=Jquery= function(){    return JQuery.fn.Init();}JQuery.fn = JQuery.prototype = {    Init:function(){        return  This;  //this point to Jquery.prototype    },    length: 1,    size: function(){        return  This.length;    }}Console.Log($().size()); //1
2. Cache the processing results
varCachedsearchbox=(function(){        varCache= {},Count=[];        return {           Attachsearchbox: function(DSID){               if(DsidinchCache{//If the results are in the cache              returnCACHE[DSID];//Directly returns objects in the cache           }               varFsb= New Uikit.WebCTRL.SearchBox(DSID);//NewCACHE[DSID]=Fsb;//Update cache           if(Count.length >  -){//Yasumasa cache size <=100              Deletecache[Count.Shift()];               }               returnFsb;                 }    };    })();         Cachedsearchbox.Attachsearchbox("Input");  

This will then be read from the cache when we call the second time.

Understand the principle of closure we find that these uses of closures are the use of closures to preserve the characteristics of the active object of the current function, so that the closure function can still access the scope of its creation when it is called outside the scope

Disadvantages of closures
    • Closures keep the active object of the function in memory, and excessive use of closures can lead to excessive memory consumption, so you need to dereference the active objects that are stored in memory after you have finished using them;
    • Closures can only get the last value of any variable in the outer function, and the result is incorrect when the loop is used with the returned function.
    • When the returned function is an anonymous function, note that this in the anonymous function refers to the Window object.

Here is just my comments on the closure, if the wrong place, but also hope that we put forward, together to exchange common progress!
Reference documents

    • "You don't know JavaScript" rolled up.
    • In-depth understanding of JavaScript series

Understanding of closures in JavaScript

Related Article

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.