A complete understanding of the closure basics in JavaScript

Source: Internet
Author: User
Tags closure garbage collection

Introduction

A closure is a function that has access to a variable in another function scope.
Closures are hard to understand in JavaScript, and many advanced applications rely on closures, so let's take a look at one of the following examples:

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

The code above, according to the scope of the variable, all the local variables in the function outer are visible to the function inner, the local variable in the function inner is not visible outside the function inner, so it is not possible to read the local variable of the function inner outside the function inner.

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

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

This function has two features:

    • function inner nested inside the function Ouer;
    • function outer return function inner.

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

Scope
Simply put, the scope is the accessible range of variables and functions, that is, the scope controls the visibility and lifecycle of variables and functions. In JavaScript, the scope of a variable has two kinds, global scope and local scope.

Global scope

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

The above three objects, num1,num2 and FUN1, are global scopes, and it is important to note that the variables defined directly by the end are automatically declared to have global scope.

Local scope

function wrap () {
  var obj = "I was wrap wrapped up, wrap can't directly access me outside";
  function Innerfun () {
    //external cannot access me
  }
}

Scope chain
everything in JavaScript is object, and these objects have a [[Scope]] property that contains a set of objects in the scope that the function was created in, called the scope Chain of the function, which determines which data can be accessed by the function.

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

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

var sum = Add (3,4);

When a function is called, an internal object called the Run-time context (execution) is created, which defines the environment at which the function executes. It also has its own scope chain, which is used for identifier resolution, and its scope chain is initialized to the objects contained in [[Scope]] of the currently running function.

During function execution, each time a variable is encountered, an identifier parsing process is experienced to determine where to get and store the data. The process from the scope chain head, that is, start the search from the active object, look for an identifier with the same name, and if you find it, use the variable for that identifier, and if you don't find the next object in the scope chain that continues the search, if all the objects (the last one is global) are not found, the identifier is undefined

Closed Bag
a closure is simply a function that accesses its external variables.

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

The status is stored in quo, which returns an object in which the method GetStatus refers to the status variable, that is, the GetStatus function accesses its external variable status;

var newvalue = Quo (' string ');/returns an anonymous object, which is referenced by NewValue
newvalue.getstatus ();//access to Quo's internal variable status

If this method is not getstatus, then the status is automatically reclaimed after quo (' sting '), because the returned anonymous object is referenced by a global object, and the anonymous object relies on status, which prevents the status from being released.

Example:

Error scheme
var test = function (nodes) {
  var i;
  for (i = 0;i<nodes.length;i++) {
    Nodes[i].onclick = function (e) {
      alert (i);
    }
  }
}

The anonymous function creates a closure, then the I that accesses is the I in the external test function, so each node actually refers to the same I.

Improved 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 binds an event that receives a parameter and runs immediately, passing in I, because it is passed by value, so each loop will generate a new backup for the current I.

The function of closure

function outer () {
  var i = m;
  function inner () {
     console.log (i++);
  }
  return inner;
}
var rs = outer ();
RS ();
rs ();
-Rs ();  102

In the code above, RS is the closure inner function. Rs ran three times, the first 100, the second 101, the third 102, which shows that the local variable i in the function outer has been saved in memory and has not been automatically cleared in the call.

The function of closures is that after the outer is executed and returned, the closure makes the JavaScript garbage collection mechanism (Grabage collection) not reclaim outer memory, because outer's internal function inner's execution relies on variables in outer. (Another explanation: outer is inner's parent function, inner is assigned to a global variable, causing inner to remain in memory, and inner's presence is dependent on outer, because outer are always in memory and will not be collected after the call ends).

Closures have access to all variables within the function.
When a function returns a closure, the scope of the function will remain in memory until the closure does not exist.

Closures and variables

Because of the mechanism of the scope chain, closures can only take the last value of any variable in the function. Look at 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] ());
}

function returns an array on the surface, it seems that each function should return its own index value, in effect, each function returns 10, because the active object of function f is preserved on the scope chain of the function, and they refer to the same variable i. When function f returns, the value of the variable i is 10, at which point each function holds the same variable object of the variable i. We can force the closure behavior to conform to expectations by creating another anonymous function.

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 release, instead of assigning the closure to the array directly, we define an anonymous function and assign the result of the immediately executing anonymous function to the array. Here the anonymous function has a parameter num, when we call each function, we pass in the variable I, and because the parameter is passed by value, the variable i is copied to the parameter num. Within this anonymous function, a closure that accesses NUM is created and returned, so that each function in the RS array has a copy of its own num variable, so it can return a different number.

The This object in the closure

var name = ' Jack ';

var o = {
  name: ' Bingdian ',

  getname:function () {return
    function () {return
      this.name;
  }
}

Console.log (O.getname () ());   Jack
var name = ' Jack ';

var o = {
  name: ' Bingdian ',

  getname:function () {
    var self = this;
    return function () {return
      self.name;}
    ;

}} Console.log (O.getname () ());   Bingdian

Memory leaks

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

The above code creates a closure that acts as an EL element event handler, and the closure creates a circular reference, as long as the anonymous function exists, El has a reference number of at least 1, and the memory it occupies will never be reclaimed.

function Assignhandler () {
  var el = document.getElementById (' demo ');
  var id = el.id;

  El.onclick = function () {
    console.log (ID);
  }

  el = null;
}
Assignhandler ();

Setting the variable El to null can lift a reference to a DOM object and ensure that it is properly reclaimed for memory consumption.

Impersonation block-level scopes

The set of statements in any pair of curly braces ({and}) belongs to a block, in which all the variables defined are not visible outside the code block, which we call block-level scopes.

(function () {
  //block-level Scope
}) ();

The application of closure package

Protect variable security within a function. As in the previous example, I can only access the function inner in the function outer, and it cannot be accessed by other means, thus protecting the security of I.
Maintain a variable in memory. As in the previous example, because of the closure, I in the function outer always exists in memory, so every time RS () is executed, I plus 1.

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.