I understand how closure

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Gradually into the closure

If this demand, write a function, dynamic generation of HTML, the HTML  one part is fixed.

Therefore

function buildHtml() {
    var template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    template[1] = args[0];
    template[3] = args[1];
    return template.join('');
}

 Analysis, the implementation of each function, will repeat the definition of template, execution of the function, the variable is destroyed; repeat the definition of destruction, definitely not good for performance, considering the variable template content extraction to the outside,

For example, after the transformation into this


$(function () {
    //...
    var template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    function buildHtml(args) {
        template[1] = args[0];
        template[3] = args[1];
        return template.join('');

    }

    //Here you can call the code above...
})

At this time, you have a demand, to move the function to other pages, when moving, you need two things, one is template and the name of the function and have not namespace variable repeat, and this structure is clearly not moving, so you think that


$(function () {
    //...
    buildHtml.template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    function buildHtml(args) {
        var template = buildHtml.template;
        template[1] = args[0];
        template[3] = args[1];
        return template.join('');
    }

    //Here you can call the code above...
})

This mobile code, seemingly don't consider two variable name repetition, we are a part of the solution. But there is a better solution, such as

var buildHtml = (function () {
    var template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    return function (args) {
        template[1] = args[0];
        template[3] = args[1];
        return template.join('');

    }

})();

  

This structure is more compact, more convenient to move this code, template is not exposed, there is the use of the closure. If (function () {...}) () usage is not familiar with, the best first google. It was not understand, I will also change under the above example.

function xx() {
    var template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    return function (args) {
        template[1] = args[0];
        template[3] = args[1];
        return template.join('');

    }
};
var buildHtml = xx();

 Then it calls buildHtml (/ * parameters*/);


Closure as provides interface or public methods to access and modify, private property. This structure, also common in private property and private methods that define an object.

For example 

var win = (function () {
    var fn1 = function () {}, //Private methods
    pro = 1; //Private property
    return {
        outFns1 : function () {
            //Call FN1 or pro
        },
        outFns2 : function () {
            //Call FN1 or pro

        }
    }
})();

 The above example, seemingly are used in return, not return? The second examples above, slightly modified, and closure

$(function () {
    //...
    var template = ['<table><tr><td>',
        '',
        '</td><td>',
        '',
        '<td></td></tr></table>'];
    buildHtml = function (args) {
        template[1] = args[0];
        template[3] = args[1];
        return template.join('');

    }

    //Here you can call the code above...
})

 BuildHtml because there is no var statement, so it is a global variable, so outside the callback function $, you can also access the template through buildHtml.

Other forms, such as the internal function is assigned to the object properties can also be, this variable can be global.


The concept of closure

Thus, to sum up what is under the closure?

In a function (here called a parent function) defined inside a function (local variables within the function to access the parent function through the scope chain), refers to the parent function returns the internal function at the end of, or in the definition of the internal function reference exposed. Perform parent function, we have made reference to the internal function, execution of the parent function, the parent function related variables occupy memory remained, still can access and modify the closure, that is to say the parent object function is maintained (here refers to the scope chain is introduced, knowledge, below) until the reference.

Closure effect looks, like provides live key value pairs, and then you can access internal function. The closure is defined when the inoculation, formed in the execution.

For this example, only to deepen the understanding of the closure. Why is “ ”.


function wrapFns() {
    var arr = [];
    for (var i = 10; i--; ) {
        arr[i] = function () {
            return i;
        }
    }
    return arr;
}
var fns = wrapFns();
console.log(fns[10]()); // What is the value of? 

Value is 0 and not 10. Of course, here you have it for 10, also have a method, here is not to say.


Closure of the application

1 as the beginning of the example, closure used to package the plug-in

You download a JS plugin in the network, basically all the plug-ins are used in the following similar structure to realize encapsulation, such privatization of variables, and can in the outside call or change the private variable value

(function (window, undefined) {
    window.ymPrompt = {}; //Can global access.
})(window);

 The 2 closure to achieve memory function

function aa(num) {
    if (num == 0) {
        return 1;
    }
    return num * aa(num - 1);
}

After transformation

var aa = (function () {
    var cache = [];
    return function (num) {
        if (!cache[num]) {
            if (num == 0) {
                cache[num] = 1;
            }
            cache[num] = num * aa(num - 1);
        }
        return cache[num];
    }
})();

Similarly, could be considered to achieve a similar situation, with the closure of “ to a function, and returns a function with memory function, ” reference to "the definitive guide P.199


3 other etc.

Such as private object methods in the above example, after all, an identifier''_ "can still be accessed.



The internal mechanism of closure and scope

A closure, relates to the concept of the scope chain, function layers of execution, the execution environment stack (the call stack in the IE debugger), identifier, parsing, the scope chain contains function within the hidden attribute [[scope]] (can only be accessed by the JavaScript engine), [[scope]] refers to the scope chain is how to produce?

Here under discussion, if the description is not clear, do not mind.

①Each function has a [[scope]] attribute, pointing to the function definition of the execution environment context. In the birth - closure.

②If A is a global function, B is the internal function of A. The A function is executed, the execution environment context refers to a scope chain, the first object chain is the object in the current function (this, parameters, local variables), second object is window.

③When executing code to run to the B definition,     [[scope]] B property for the current execution context.

④The B function is executed, the JavaScript engine will execution environment on a stack, and generate new execution environment, the implementation of environmental context to a scope chain, the first object chain is the object in the current function (this, parameters, local variables), second movable object is a A function, third window.

⑤The B function to access a variable, for symbol analysis (JavaScript prototype has identifier resolution), it starts from the first object to find the scope chain to the current context, can not find it to find second objects, until you find the correlation value return immediately, if not found, reported undefined error.

⑥If the A function is only defined the B function, and then execute it, and did not return to the external. When the A function is executed, the A occupied memory to recovery.

If the B function reference to the external, while its [[scope]] (active objects, such as the parent function in [[scope]] A active object) will be maintained, when the B function is called again, still can range. In this generation -- closure.


The scope chain to temporarily change the situation

a,Such as the use of with (obj) {}, try{}catch (obj) {}, adds obj to the front of the scope chain, other active objects corresponding after moving a bit, until the end of the with.

b,Use Function to define the function object, the [[scope]] property set to window function object.


Because I see mostly is the translation of foreign concepts, change, unlike textbooks that are inflexible clearly, understanding when to work, borrowing the concepts in this article, also don't know accurately.


this

Is actually very simple, like a fool to remember one point on the line.

Execution, see where the function is a method object is a separate function? Separate the function this===window; object method, this = = object.

function A() {
    function B() {
        console.log(this === window); //Function true alone
    }
    this.a = 1;
}
A.method = function () {
    console.log(this.a); //1 object method, this===A
}
var fn = A.method;
fn(); //Undefined single function

  

Closure notice 

As the first example, be careful not to forget to give functions plus VaR, produced the closure, local variables inside the external function is not released, if it is a rich client applications, such as you click on a control page, through a series of program logic, called nested function very deep in a layer, call, produced a series of closure, long-term accumulation, memory consumption is more and more big, the page response more slowly.

In short, if you do not have a deep understanding of the JavaScript syntax is very easy to have the closure, causing performance problems. For example, we develop the usual project, is based on the process oriented programming, each function definition function, and then press the function assembled together, function according to the function assembled together, did not follow the JavaScript specification code.


1,Because of the long-term closure variables occupy memory, so don't use them, pay attention to the accidental introduction closure.

One such constructor

function Construtor() {
    var aa;
    this.aa = '1';
    this.fun1 = function () {};
    this.fun2 = function () {};
    this.fun3...
}

 AA is not used in fun1 fun2 fun3, there is no need to use a closure, Construtor.prototype.fun1 = function(){}

Step back and say, even if you are using AA, which can be named this.aaa, and then this.aaa access.



2,We use a closure, can not continue to call the local variables in the parent function at the end of the set to null.


Some summary

1,A function can access any variable, it depends on the definition of the code location or context, rather than the execution context.

2,Closure as provides interface or public methods to access and modify, private property, and keep the private variables do not destroy.

3,This is very simple.


Write while think, example is readily did not write a test, but it should be no problem, there are errors, language is not smooth, said Wang; later also think of something, and then add it.

The first

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Anita at November 14, 2013 - 11:15 PM