Closures, scope chains, garbage collection, memory leaks

Source: Internet
Author: User
Tags variable scope

About closures, I turned a few times the book, watched a few times the video, looked up some information, but still vaguely, simply make a summary of their own! Welcome to correct me ... (~ o ~) ~zz

1. What is a closure?

Look at some definitions of closures:

    1. Closures are functions that have access to variables in another function scope--"JS Advanced Programming third Edition" p178
    2. Function objects can be linked by a scope chain, and variables inside the function body can be stored within the scope of the function, which is called ' closures '. --"JS authoritative guide" p183
    3. Intrinsic functions can access parameters and variables (in addition to and) of external functions that define them this arguments . --"JS language essence" p36

A definition summary.

    1. You can access variables in the scope of an external function.函数
    2. Variables for external functions accessed by internal functions can be stored in the scope of an external function without being recycled---this is the core, and later we encounter closures, we have to focus on the variables referenced by the closure.

To create a simple closure.

var function () {    var name = ' Jozo ';     return function () {        alert (name);    }}; var say = sayname (); Say ();

To interpret the following two statements:

    • var say = sayName(): Returned an anonymous intrinsic function stored in the variable say, and referenced the variable name of the external function, because the garbage collection mechanism, after the Sayname function is executed, the variable name is not destroyed.
    • say(): Executes the returned intrinsic function, still accesses the variable name, and Outputs ' Jozo '.
2. Scope chain in closures

Understanding the scope chain is also helpful in understanding closures.

Variables in the scope of the search should be familiar with, in fact, this is the scope of the chain to look up.

When the function is invoked:

    1. First, create an execution environment (execution context), and the corresponding scope chain;
    2. Add the values of arguments and other named parameters to the active object of the function (Activation object)

Scope Chain: The active object of the current function has the highest priority, the active object of the outer function is the second, and the active object of the external function of the outer function decrements sequentially until the end of the scope chain-the global scope. Priority is the order in which variables are searched;

Let's look at a common scope chain:

function Sayname (name) {    return  name;} var say = Sayname (' Jozo ');

This code contains two scopes: global scope, the scope of the Sayname function, that is, a. b. only two variable objects, when executed into the corresponding execution environment, the variable object becomes the active object, and is pushed into the execution environment scope chain of the front end, that is, the highest priority. Look at the words:

This figure is also in the JS high-level programming book, I re-painted all over.

When the Sayname () function is created, a scope chain of pre-contained variable objects is created, which is the scope chain with index 1 in the diagram, and is saved to the internal [Scope] property, and when the Sayname () function is called, an execution environment is created and then the [ [Scope]] The object in the property is built into a functioning domain chain, and thereafter an active object (the index in the figure 0) is created and pushed into the front end of the execution environment scope chain.

In general, when the function is finished, the local active object is destroyed and only the global scope is saved in memory. However, closures may be different:

Let's look at the scope chain of closures:

function Sayname (name) {    returnfunction() {        return  name;}    } var say = Sayname (' Jozo ');

This closure instance has more scope for an anonymous function than the previous example:

After the anonymous function is returned from the Sayname () function, its scope chain is initialized to the active object and the global variable object that contains the Sayname () function. In this way, the anonymous function can access all the variables and parameters defined in Sayname (), and more importantly, the Sayname () function will not be destroyed after execution, because the scope chain of the anonymous function is still referencing the active object, in other words, sayname () After the function executes, the scope chain of its execution environment is destroyed, but his active object is left in memory, knowing that the anonymous function will be destroyed. This is also the problem of memory leaks to be talked about later.

Scope chain problem don't write so much, write books on the things are also very tired O (╯-╰) o

3. Examples of closures

Example 1: Implementing accumulation

//Mode 1varA = 0;varAdd =function() {a++; Console.log (a)}add (); Add ();//Mode 2: ClosuresvarAdd = (function(){    varA = 0; return function() {a++;    Console.log (a); }}); Console.log (a); //undefinedAdd (); add ();

相比之下方式2更加优雅,也减少全局变量,将变量私有化

Example 2: Add a Click event to each Li

var oli = document.getelementsbytagname (' li 'varfor (i = 0;i < 5;i++ {     function() {         alert (i);      // 5 // Execute anonymous function (function() {    alert (i);   // 5 } ());

The above is a classic example, we all know that the execution results are all pop up 5, but also know that the closure can be used to solve the problem, but I just started to understand why each popup is 5, why closures can solve the problem. Then I smoothed it out or made it clear:

A. First to analyze the situation before the use of closures: For loop, we give each Li Click event binding an anonymous function, the anonymous function returns the value of the variable I, when the loop ends, the value of the variable I becomes 5, then we click on each Li, that is, to execute the corresponding anonymous function (see the above code), This is the variable i is already 5, so each click POPs up 5. Because each of the anonymous functions returned here refers to the same variable i, if we create a new variable to save the current value of I at the time of execution of the loop, then let the anonymous function apply the variable, and then return the anonymous function, so that we can achieve our goal, which is the use of closures to achieve!

B. To analyze the situation when using closures:

  var oli = document.getelementsbytagname (' li ');      var i;       for (i = 0;i < 5;i++) {         = (function(num) {             var//  To illustrate the problem             returnfunction() {                 alert (a);             }         }) (i)     }      // 5

Here for the For loop execution, the anonymous function that gives the Click event binding immediately executes returns an internal anonymous function, because the parameter is passed by value, so the formal parameter num holds the value of the current I, then assigns the value to the local variable a, and then the internal anonymous function keeps a reference to a. That is, the value of the current I is preserved. So after the loop has finished clicking on each Li, the returned anonymous function executes the value that pops up the reference of the respective saved a.

4. Application of closures

Let's take a look at the use of closures. In fact, we can do a lot of things by using closures. such as simulating object-oriented code style, more elegant, more concise expression of code, in some ways to improve the efficiency of code execution.

1. Anonymous self-executing functions

We often encounter situations where a function needs to be executed only once and its internal variables need not be maintained, such as the initialization of the UI, then we can use closures:

// Turn all Li fonts to red (function() {        var els = document.getelementsbytagname (' li ');      for (var i = 0,lng = Els.length;i < lng;i++) {        = ' red ';    }    }) ();  

We created an anonymous function and immediately executed it, because the external cannot reference its internal variables,
So els,i,lng these local variables will be released soon after execution, saving memory!
The key is that this mechanism does not pollute global objects.

2. Implementing encapsulated/Modular Code

varperson=function(){        //variable scope is inside function, external unreachable    varName = "Default"; return{getName:function(){               returnname; }, SetName:function(newName) {name=NewName; }}} (); Console.log (Person.name) ;//direct access with a result of undefinedConsole.log (Person.getname ());//defaultPerson.setname ("Jozo");  Console.log (Person.getname ()); //Jozo

3. Implementing Object-oriented objects
Such different objects (instances of classes) have independent members and states, and do not interfere with each other. Although there is no such mechanism in JavaScript, by using closures,
We can simulate such a mechanism. Or in the above example:

functionPerson () {varName = "Default"; return{getName:function(){               returnname; }, SetName:function(newName) {name=NewName;    }        }    }; varperson1=Person ();    Print (Person1.getname ()); John.setname ("Person1");  Print (Person1.getname ()); //Person1varPerson2=Person ();    Print (Person2.getname ()); Jack.setname ("Erson2");  Print (Erson2.getname ()); //Person2

Two instances of person person1 and person2 do not interfere with each other! Because these two instances are independent of the access of this member to name.

5. Memory Leaks and solutions

Garbage collection mechanism

When it comes to memory management, there are two strategies for garbage collection: Tag cleanup and reference counting, which are naturally inseparable from the garbage collection mechanism in JS.

标记清除:The garbage collector adds tags to all variables stored in memory at run time, and then it strips out tags of variables in the environment and tags of variables referenced by variables in the environment, after which, if the variable is marked again, the variable is ready to be deleted. Until 2008, Ie,firefox,opera,chrome,safari's JavaScript was used in this way;

引用计数:Tracking records the number of times each value is referenced, and when a variable is declared and a value of a reference type is assigned to the variable, the reference count is 1, and if the value is again assigned to another variable, the number of references is added to 1. Conversely, if a variable is out of a reference to that value, the value is reduced by 1, and when the number of times is 0 o'clock, it waits for the garbage collector to recycle.

A big problem with this approach is the circular reference, which means that the A object contains a pointer to B, and object B also contains a reference to a. This can result in large amounts of memory not being recycled (memory leaks), because their references can never be 0. An early version of IE (IE4-IE6) uses a garbage collection mechanism that is counted, and one of the reasons that closures cause memory leaks is a flaw in the algorithm.

We know that some of the objects in IE are not native-level JavaScript objects, for example, objects in the BOM and Dom are implemented as COM objects, whereas the garbage collection mechanism of COM objects uses reference counting. Therefore, although the JavaScript engine of IE uses the tag purge policy, the Access COM object is still based on reference counting, so as long as the design of COM objects in IE there will be a circular reference problem!

Give me a chestnut:

function () {    var el = document.getElementById ("id");     function () {        alert (el.id);    }}

Why is this code causing a memory leak?

function () {    alert (el.id);};

When executing this code, the anonymous function object is assigned to the OnClick property of El, and then the El object is referenced inside the anonymous function, and there is a circular reference, so it cannot be recycled;

Workaround:

function () {    var el = document.getElementById ("id");     var // To dismiss a circular reference    function () {        alert (ID);     }     NULL // clears the active object in the outer function referenced by the closure }

6. Summarize the pros and cons of closures

Advantages:

    • You can make a variable reside in memory (if you use more, it becomes a disadvantage.)
    • Avoid contamination of global variables
    • Privatization variables

Disadvantages

    • Because the closure carries the scope of the function that contains it, it consumes more memory than the other functions
    • Cause a memory leak

Closures, scope chains, garbage collection, memory leaks

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.