Fully understand the closures in JavaScript and understand javascript

Source: Internet
Author: User

Fully understand the closures in JavaScript and understand javascript

Introduction

A closure is a function that has the right to access variables in another function scope.
Closures are hard to understand in javascript. Many advanced applications rely on closures. Let's look at the following example:

function outer() {  var i = 100;  function inner() {    console.log(i);  }}

The code above indicates that all the local variables in the function outer are visible to the function inner according to the scope of the variable. The local variables in the function inner are invisible outside the function inner, therefore, local variables of the function inner cannot be read outside the function inner.

Since the function inner can read the local variables of the function outer, as long as the inner is used as the return value, the inner's local variables can be directly read outside the ouer.

function outer() {  var i = 100;  function inner() {     console.log(i);  }  return inner;}var rs = outer();rs();

This function has two features:

  • The inner of the function is nested in the ouer of the function;
  • The function outer returns the function inner.

After var rs = outer () is executed, the actual rs points to the inner function. This code is actually a closure. That is to say, when the inner of the function outer is referenced by a variable outside the function outer, a closure is created.

Scope
In short, the scope is the accessible scope of variables and functions, that is, the scope controls the visibility and lifecycle of variables and functions. In JavaScript, variables have two scopes: global scope and local scope.

GLOBAL SCOPE

var num1 = 1;function fun1 (){  num2 = 2;}

The preceding three objects num1, num2, and fun1 are both global scopes. Note that the variables directly assigned at the end are automatically declared as having a global scope;

Local Scope

Function wrap () {var obj = "I have been wrapped up by wrap and cannot be directly accessed from outside wrap"; function innerFun () {// cannot be accessed from outside }}

Scope chain
All objects in Javascript are objects. These objects have a [[Scope] attribute that contains a set of objects in the Scope created by the function, this set is called the Scope Chain of a function. It determines which data can be accessed by the function.

function add(a,b){  return a+b;}

When a function is created, its [[scope] attribute automatically adds a global scope.

var sum = add(3,4);

When a function is called, an internal object called execution context is created. The z object defines the environment in which the function is executed. It also has its own Scope chain for identifier parsing, and its Scope chain is initialized to the objects contained in the [[Scope] of the currently running function.

During function execution, every time a variable is encountered, an identifier parsing process is performed to determine where to obtain and store data. This process searches for identifiers with the same name from the scope chain header, that is, from the activity object. If the identifiers are found, the variables corresponding to the identifiers are used, if the next object in the scope chain is not found, and all objects (the last one is a global object) are not found, the identifier is considered undefined.

Closure
A closure is simply a function that accesses its external variables.

var quo = function(status){  return {    getStatus: function(){      return status;    }  }}

Status is saved in quo, And it returns an object. The getStatus method in this object references this status variable, that is, the getStatus function accesses its external variable status;

Var newValue = quo ('string'); // an anonymous object is returned and newValue. getStatus () is referenced by newValue. // The internal variable status of quo is accessed.

If the getStatus method is not used, the status is automatically recycled after the quo ('sting ') ends. It is precisely because the returned anonymous object is referenced by a global object, this anonymous object depends on status again, so it will prevent the release of status.

Example:

// Error solution var test = function (nodes) {var I; for (I = 0; I <nodes. length; I ++) {nodes [I]. onclick = function (e) {alert (I );}}}

When an anonymous function creates a closure, the I It accesses is the I in the external test function, so each node actually references the same I.

// Improvement Scheme var test = function (nodes) {var I; for (I = 0; I <nodes. length; I ++) {nodes [I]. onclick = function (I) {return function () {alert (I) ;}}( I );}}

Each node is bound with an event. This event receives a parameter and runs immediately and passes in I because it is passed by value, therefore, each cycle generates a new backup for the current I.

Function of closure

function outer() {  var i = 100;  function inner() {     console.log(i++);  }  return inner;}var rs = outer();rs();  //100rs();  //101rs();  //102

In the code above, rs is the inner function of the closure. Rs runs three times in total, 100 for the first time, 101 for the second time, and 102 for the third time. This indicates that the local variable I in the function outer has been stored in the memory and is not automatically cleared during the call.

The function of the closure is that after the outer is executed and returned, the closure makes the grabage collection of javascript not recycle the memory occupied by the outer, because the inner execution of the internal function of outer depends on the variables in outer. (Another explanation: outer is the parent function of inner. inner is assigned a global variable, so that inner is always in the memory, and inner is dependent on outer, because some outer is always in the memory and will not be collected and recycled after the call is completed ).

The closure has the right to access all variables in the function.
When a function returns a closure, the function's scope will remain in the memory until the closure does not exist.

Closure and variable

Because of the mechanism of the scope chain, the closure can only obtain the last value of any variable in the function. Take the following example:

Function f () {var rs = []; for (var I = 0; I <10; I ++) {rs [I] = function () {return I ;}}return rs ;}var fn = f (); for (var I = 0; I <fn. length; I ++) {console. log ('function fn ['+ I +'] () Return Value: '+ fn [I] ();}

The function returns an array. On the surface, it seems that every function should return its own index value. In fact, every function returns 10, this is because the scope chain of the first function stores the activity objects of function f, which reference the same variable I. When function f returns, the value of variable I is 10. At this time, each function stores the same variable object of variable I. We can create another anonymous function to force the closure to behave as expected.

Function f () {var rs = []; for (var I = 0; I <10; I ++) {rs [I] = function (num) {return function () {return num ;};} (I) ;}return rs ;}var fn = f (); for (var I = 0; I <fn. length; I ++) {console. log ('function fn ['+ I +'] () Return Value: '+ fn [I] ();}

In this version, we did not directly assign the closure value to the array. Instead, we defined an anonymous function and assigned the result of immediately executing the anonymous function to the array. Here, the anonymous function has a parameter num. When calling each function, we pass in the variable I. Because the parameter is passed by value, we will copy the variable I to the parameter num. In this anonymous function, a closure accessing num is created and returned. In this way, each function in the rs array has a copy of its own num variable, therefore, different values can be returned.

This object in the closure

var name = 'Jack';var o = {  name : 'bingdian',  getName : function() {    return function() {      return this.name;    };  }}console.log(o.getName()());   //Jackvar name = 'Jack';var o = {  name : 'bingdian',  getName : function() {    var self = this;    return function() {      return self.name;    };  }}console.log(o.getName()());   //bingdian

Memory leakage

function assignHandler() {  var el = document.getElementById('demo');  el.onclick = function() {    console.log(el.id);  }}assignHandler();

The code above creates a closure that serves as the el Element event handler, and this closure creates a circular reference. As long as an anonymous function exists, the number of el references must be at least 1, because the memory occupied by it will never be recycled.

function assignHandler() {  var el = document.getElementById('demo');  var id = el.id;  el.onclick = function() {    console.log(id);  }  el = null;}assignHandler();

Setting the null variable el can remove the reference of the DOM object and ensure that the occupied memory is recycled normally.

Simulate block-level scope

The statement set in any pair of curly braces ({And}) belongs to a block. All variables defined in this block are invisible outside the block, which is called block-level scope.

(Function () {// block-level scope })();

Closure Application

Protect the security of variables in the function. As in the previous example, in function outer, I can only be accessed by function inner, but cannot be accessed through other channels, thus protecting the security of I.
Maintain a variable in the memory. As in the previous example, because of the closure, the I in the outer function has always existed in the memory, so each execution of rs () will add 1 to I.

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.