Understanding closures in javascript

Source: Internet
Author: User
This article describes the features, functions, sample code, and precautions of closures in javascript. It has a certain reference value. Let's take a look at the contents below.

What is a closure?

Features of closures

Function of closure:

Code example of closure

Notes

Summary

Closures are an important concept in javascript, and many technologies are also used in daily work. To make a small summary.

What is a closure?

Official statement:

A closure is a function that has the right to access variables in another function scope. A common way to create a closure is to create another function within a function and access the local variables of the function through another function.

The following is a simple closure:

function A(){ var text="hello world"; function B(){ console.log(text); } return B;}var c=A();c(); // hello world 

Literally, function B has the right to access the variable (text) in function A's scope and access the local variable text of the function through another function C. Therefore, function B forms a closure. It can also be said that C is a closure, because C actually executes function B.

Note that the direct execution of A (); has no response. Because return B is not executed, unless it is return B ();

Features of closures

Closures have three features:

1. nested Functions

2. The function can reference external parameters and variables.

3. Parameters and variables are not recycled by the garbage collection mechanism.

Let's explain why the closure parameters and variables are not recycled by the garbage collection mechanism?

First, let's take a look at the principle of garbage collection in javascript:

(1) In javascript, if an object is no longer referenced, the object will be recycled by GC (garbage collection;

(2) If two objects reference each other and are no longer referenced by 3rd, the two objects will be recycled.

In the above sample code, A is the parent function of B, and B is assigned to A global variable C (the life cycle of the global variable will not end until the browser uninstalls the page ), as A result, B is always in the memory, and B is dependent on A. Therefore, A is always in the memory and will not be recycled by the garbage collection mechanism after the call is complete.

Function of closure:

In fact, the function of the closure is also determined by the characteristics of the closure. According to the closure features above, the function of the closure is as follows:

1. You can read the internal variables of the function, instead of defining global variables together to avoid environmental pollution.

2. Keep the values of these variables in the memory.

Code example of closure

The following describes several common closures and analyzes them:

The sum of local variables of demo1.

Function countFn () {var count = 1; return function () {// function nested function count ++; console. log (count) ;}}var y = countFn (); // The external function is assigned to the variable y; y (); // 2 // The y function is called once, the result is 2, which is equivalent to the second call of the countFn () y (); // 3 // y function. The result is 3, because the count of the last call is still stored in the memory and has not been destroyed, the accumulated y = null is implemented; // garbage collection, releasing the memory y (); // y is not a function

Since the first execution is complete, the variable count is stored in the memory, so it will not be recycled, so that the value of the last operation can be accumulated during the second execution. When y = null is introduced, the reference is destroyed and the memory is released.

Use closure in demo2 Loop

The Code is as follows (the following three sample codes): We want to call the serial number of a loop in each loop:

Demo2-1

For (var I = 0; I <10; I ++) {var a = function () {console. log (I)} a () // 0-9 in sequence}

The result of this example is no question. We printed 0-9 in sequence.

Each layer of anonymous functions and variable I constitute a closure, but this is no problem in the loop, because the function is immediately executed in the loop body.

Demo2-2

But it is different in setTimeout.

For (var I = 0; I <10; I ++) {setTimeout (function () {console. log (I); // 10 times 10}, 1000 );}

We expect to print 0-10 in sequence, but the actual situation is to print 10 times. Even if the setTimeout time is changed to 0, 10 10 are printed. Why?

This is because of a mechanism of setTimeout. setTimeout starts timing from the end of the task queue. If the previous process is not finished, it will wait until it ends and start timing. Here, the task queue is its own loop.

The timer starts when the cycle ends. Therefore, the I in setTimeout is the last cycle I in any case. In this Code, the final I is 10, so 10 10 are printed.

This is why the setTimeout callback is not the value of every loop, but the last value.

Demo2-3

Solve the problem that the preceding setTimeout cannot print out the loop in sequence.

For (var I = 0; I <10; I ++) {var a = function (e) {return function () {console. log (e); // enter 0-9 in sequence} setTimeout (a (I), 0 );}

Because the first parameter setTimeout requires a function, a function is returned to it. At the same time, I is passed as a parameter, and I is cached through the form parameter e, that is to say, the e variable is equivalent to a copy of I and brought into the returned function.

When setTimeout is executed, it has a reference to e, and this value will not be changed cyclically.

You can also use the following statement, similar to the above:

For (var I = 0; I <10; I ++) {(function (e) {setTimeout (function () {console. log (e); // print 0-9}, 0) ;}) (I );}

Add events in the demo3 Loop

Let's take a look at the following typical demo.

We want alert to output the index value of li every time we click li, so use the following code:

 
 
  • First
  • Second
  • Third
  • Fourth
Var nodes = document. getElementsByTagName ("li"); for (I = 0, len = nodes. length; I

Contrary to expectations, no matter which li you click, it is alert (4), that is, the index value after the end of the alert loop. Why?

This is because events are bound to different elements in the loop. If a variable related to the loop is called in the Event Callback Function, the variable takes the last value of the loop.

Since the bound callback function is an anonymous function, in the code above, this anonymous function is a closure and carries an outer scope (that is, the scope in ), when an event is triggered, the variables in the scope have reached the end with the loop.

Another point is that an event needs to be triggered. In most cases, the cycle has ended when triggered, so the variable related to the loop is the last value.

To click li and alert to output the index value of li, you need to modify the above Code as follows:

   
  
  • First
  • Second
  • Third
  • Fourth
Var nodes = document. getElementsByTagName ("li"); for (var I = 0; I

Solution: add several corresponding closure domain spaces (anonymous functions are used here) to store the content to be referenced (subscript ).

When the function is executed immediately, the e value will not be destroyed, because it contains an anonymous function (or it can be said that the variable will not be destroyed because of the existence of the closure ). After execution, the relationship between the e value and global variable I is cut off,

That is to say, the number of I that is passed during execution and the number of e that executes the function immediately, but the value of e does not disappear because of the existence of anonymous functions.

You can also use the following solution. The principle is the same:

     
   
  • First
  • Second
  • Third
  • Fourth
Var nodes = document. getElementsByTagName ('lil'); for (var I = 0; I

Notes

1. Memory leakage

Since closures carry the scopes of the functions that contain them, they occupy more memory than other functions. Excessive use of closures may cause excessive memory usage. Therefore, you must consider using closures when necessary.

2. Using this in closures may also cause some problems.

In fact, we want alert to output the name in the object.

var name="The Window"; var object={ name:"My Object", getNameFunc:function(){  return function(){  return this.name;  } } } alert(object.getNameFunc()()); // The Window

In a global function, this is equal to window. When a function is called as a method of an object, this is equal to that object. However, the execution environment of anonymous functions is global, so this object usually points to window.

When a function is called, it automatically retrieves two special variables: this and arguments. When searching for these two variables, internal functions only search for the active objects. That is to say, the return function will only search

To the global this, stop searching. Because it will never directly access these two variables in the external function.

Make a slight modification to save this object in the external scope in a variable that can be accessed by a closure. In this way, the closure can access this object.

var name="The Window"; var object={ name:"My Object", getNameFunc:function(){  var that=this;  return function(){  return that.name;  } } } alert(object.getNameFunc()()); // My Object

We assigned this object to that variable. After the closure is defined, the closure can also access this variable. Therefore, even after the function returns, that still references this object. Therefore, if you call object. getNameFunc (), "My Object" is returned.

Summary

When other functions are defined in the function, the closure is created. The closure has the right to access all variables within the function.

The scope of a closure includes its own scope, the scope of the function, and the global scope.

When a function returns a closure, the function's scope will remain in the memory until the closure does not exist.

When using closures, additional scopes must be maintained. Excessive use of closures may occupy a large amount of memory.

The above is all the content of this article. I hope this article will help you in your study or work, and I also hope to support PHP!

For more information about closures in javascript, see the PHP Chinese website!

Related Article

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.