Summary of knowledge about JS closures, scope chains, garbage collection, memory leaks

Source: Internet
Author: User
Tags variable scope
<span id="Label3"></p><p><p><strong>Add:</strong></p></p><p><p>Closures (closure) are a difficult and unique feature of the JavaScript language, and many advanced applications rely on Closures.</p></p><p><p></p></p><p><p><strong>Closure of</strong> <strong style="line-height: 1.5;">three features:</strong></p></p><p><p>1. Function Nesting functions</p></p><p><p>2. External parameters and variables can be referenced inside the function</p></p><p><p>3. Parameters and variables are not recycled by the garbage collection mechanism</p></p><p><p></p></p><p><p><strong>The definition of closures and their advantages and disadvantages:</strong></p></p><p><p>Closures are functions that have access to variables in another function scope, and the most common way to create closures is to create another function within one function and access the local variables of the function through another Function.</p></p><p><p>The disadvantage of closures is that resident memory increases memory usage and is prone to memory leaks if used improperly.</p></p><p><p>Closures are a major feature of the JavaScript language and are mainly used in closures to: design private methods and Variables.</p></p><p><p>After the general function is executed, the local active object is destroyed and only the global scope is saved in Memory. But the case of closures is different!</p></p><p><p></p></p><p><p><strong>Talk around the subject</strong></p></p><p><p><strong>1. What is the definition of closures?</strong></p></p><p><p><strong>Look at some definitions of closures:</strong></p></p><p><p>1. Closures refer to functions that have access to variables in another function scope</p></p><p><p>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 '.</p></p><p><p>3. Intrinsic functions can access parameters and variables (except this and arguments) that define their external functions.</p></p><p><p><strong></strong></p></p><p><p><strong>A definition Summary.</strong></p></p><p><p>1. Functions that can access variables in the scope of an external function</p></p><p><p>2. Variables of external functions accessed by internal functions can be stored in the scope of an external function without being recycled---this is the core, we have to think of closures later, we have to focus on the variables referenced by the Closure.</p></p><p><p>To create a simple closure.</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">var sayname = function () { var name = ' Jozo '; return function () { alert (name); }}; var say = Sayname (); say ();</pre></pre><p><p></p></p><p><p>To interpret the following two statements:</p></p><p><p>var say = Sayname (): Returns an anonymous intrinsic function stored in the variable say, and references the variable name of the external function, because the garbage collection mechanism, after the Sayname function is executed, the variable name is not Destroyed.</p></p><p><p>Say (): executes the returned intrinsic function and still accesses the variable name, outputting ' Jozo '.</p></p><p><p></p></p><p><p><strong>2. Scope chain in closures</strong></p></p><p><p>Understanding the scope chain is also helpful in understanding Closures.</p></p><p><p>Variables in the scope of the search should be familiar with, in fact, this is the scope of the chain to look up.</p></p><p><p>When the function is Invoked:</p></p><p><p>1. First create an execution environment (execution context), and the corresponding scope chain;</p></p><p><p>2. Add the values of arguments and other named parameters to the active object of the function (activation Object)</p></p><p><p>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;</p></p><p><p>Let's look at a common scope chain:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">function Sayname (name) { return name;} var say = Sayname (' Jozo ');</pre></pre><p><p>  </p></p><p><p>This code contains two scopes: A. Global scope; the scope of the B.sayname function, that is, only two variable objects, when executed into the corresponding execution environment, the variable object becomes the active object and is pushed into the front end of the execution environment scope chain, which is the highest Priority. Look at the Words:</p></p><p><p>This figure is also in the JS high-level programming book, I re-painted all over.</p></p><p><p>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.</p></p><p><p>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:</p></p><p><p>Let's look at the scope chain of closures:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">function Sayname (name) { return function () { return name;} } var say = Sayname (' Jozo ');</pre></pre><p><p>  </p></p><p><p>This closure instance has more scope for an anonymous function than the previous example:</p></p><p><p>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 until the anonymous function is Destroyed. This is also the problem of memory leaks to be talked about Later.</p></p><p><p>Scope chain problem don't write so much, write books on the things are also very tired o (╯-╰) o</p></p><p><p></p></p><p><p><strong>3. Examples of closures</strong></p></p><p><p><strong>Example 1: implementing accumulation</strong></p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">Mode 1var A = 0;var add = function () { a++; Console.log (a)}add (); Add ();//mode 2: closed var add = (function () { var a = 0; return function () { a++; Console.log (a); }}) (); Console.log (a); Undefinedadd (); Add ();</pre></pre><p><p>  </p></p><p><p>By contrast, Mode 2 is more elegant and also reduces global variables, privatizing variables</p></p><p><p><strong>Example 2: add a click event to each Li</strong></p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">var oli = document.getElementsByTagName (' Li '); var i;for (i = 0; i < 5; i++) { Oli[i].onclick = function () { al ERT (i); }} Console.log (i); 5//performs anonymous functions (function () { alert (i);//5} ());</pre></pre><p><p>  </p></p><p><p>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:</p></p><p><p>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!</p></p><p><p>B. To analyze the situation when using closures:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">var oli = document.getElementsByTagName (' Li '), var i;for (i = 0; i < 5; i++) { Oli[i].onclick = (function (num) { <c5 />var A = num; To illustrate the problem return function () { alert (a); } }) (i)} Console.log (i); 5</pre></pre><p><p>  </p></p><p><p>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.</p></p><p><p></p></p><p><p><strong>4. Application of closures</strong></p></p><p><p>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.</p></p><p><p><strong>1. Anonymous self-executing functions<br></strong></p></p><p><p>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:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">Turns all Li fonts to red (function () { var els = document.getelementsbytagname (' li '); for (var i = 0, LNG = els.length; i < lng; i++) { els[i].style.color = ' Red '; }}) ();</pre></pre><p><p></p></p><p><p>We create an anonymous function and execute it immediately, because the external cannot reference its internal variables, so els,i,lng These local variables will be released soon after execution, saving memory!</p></p><p><p>The key is that this mechanism does not pollute global objects.</p></p><p><p><strong>2. Implementing Encapsulated/modular Code</strong></p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">var person = function () { //variable scope is inside function, external cannot access var name = "default"; return { getname:function () { return name; }, 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</pre></pre><p><p></p></p><p><p><strong>3. Implementing object-oriented Objects</strong></p></p><p><p>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, we can simulate such a mechanism by using closures. Or in the above example:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">function Person () { var name = "default"; return { getname:function () { return name; }, setname:function (newName) { name = newName; } }}; var person1 = person ();p erson1.getname ();p erson1.setname ("person1");p erson1.getname (); Person1var Person2 = person ();p erson2.getname ();p erson2.setname ("person2");p erson2.getname (); Person2</pre></pre><p><p></p></p><p><p>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.</p></p><p><p></p></p><p><p><strong>5. Memory Leaks and solutions</strong></p></p><p><p><strong>Garbage collection mechanism<br></strong></p></p><p><p>When it comes to memory management, <strong>There are two strategies for garbage collection: tag cleanup and reference counting</strong> , which are naturally inseparable from the garbage collection mechanism in Js.</p></p><p><p><strong>Mark Clear:</strong> the garbage collector will tag all variables stored in memory at run time, and then it will remove the tags of variables in the environment and the 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;</p></p><p><p><strong>reference Count:</strong> the number of times each value is referenced, when a variable is declared and the value of a reference type is assigned to the variable, the number of references to that value is 1, and if the value is 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.</p></p><p><p>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.</p></p><p><p>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!</p></p><p><p>Give me a chestnut:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">window.onload = function () { var el = document.getElementById ("id"); El.onclick = function () { alert (el.id); }}</pre></pre><br><p><p>Why is this code causing a memory leak?</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">El.onclick = function () { alert (el.id);};</pre></pre><p><p>  </p></p><p><p>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;</p></p><p><p>Workaround:</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">window.onload = function () { var el = document.getElementById ("id"); var id = el.id; Unbind the circular reference El.onclick = function () { alert (id); } El = null; Clears the active object in the outer function referenced by the closure}</pre></pre><br><p><p>Summary of knowledge about JS closures, scope chains, garbage collection, memory leaks</p></p></span>

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.