Closures in JavaScript

Source: Internet
Author: User
Tags closure

Previous words:

Closures, is an important concept in JavaScript, for beginners, closures are a particularly abstract concept, especially the ECMA specification to the definition, if there is no actual combat experience, you can not understand it from the definition. Here's how the author slowly talks about closures from the scope chain and later mentions some of the advanced uses of closures. Now let's learn about closures in JavaScript.

A talk about JavaScript scope chain

When a piece of JavaScript code (global code or function) is executed, the JavaScript engine creates a scope for it, also known as the execution context (execution context), after the page loads, it first creates a global scope, and then each function executes, A corresponding scope is created, thus forming a chain of scopes. Each scope has a corresponding scope chain, the chain head is the global scope, the chain tail is the current function scope.

The role of the scope chain is to parse the identifier, and when the function is created (not executed), the This, arguments, named argument, and all local variables in the function are added to the current scope, and when JavaScript needs to find the variable x (this process is called variable resolution), It will first look for the X attribute from the chain end in the scope chain, which is the current scope, and if it is not found, follow the scope chain to continue the lookup until the variable is found in the chain header, which is the global scope chain, and it is assumed that there is no X variable on the scope chain of the code. and throws a reference error (REFERENCEERROR) to the exception.

Look at the following example:

Defines the global variable color, which is applicable globally, where global variables colorvar color = "Red" can be used everywhere, function ChangeColor () {//in ChangeColor ()        The function internally defines the local variable anothercolor, only valid in function ChangeColor () var anothercolor = "Blue";        function Swapcolor () {//within the Swapcolor () function defines the local variable tempcolor, only valid in function Swapcolor () var tempcolor = Anothercolor;        Anothercolor = color;                color = Tempcolor;                You can access color, Anothercolor, and Tempcolor console.log (color) here;        Blue Console.log (Anothercolor);            Red Console.log (Tempcolor);    Blue} swapcolor ();                Only color can be accessed here, Anothercolor, Tempcolor console.log (color) cannot be accessed;        Blue Console.log (Anothercolor);            Anothercolor is not defined Console.log (Tempcolor);                Tempcolor is not defined}changecolor ();//This can only be accessed colorconsole.log (color);        Blueconsole.log (Anothercolor);            Anothercolor is not definedconsole.log (Tempcolor); Tempcolor is not defined

There are several pits to note:

1. Advance declaration of Var and functions
var color = "Red"; function ChangeColor () {    var color = "Yellow";    return color;} var result = ChangeColor (); Console.log (result);

Again such as:

function fn (a) {  console.log (a);   var a = 2;  function A () {}  Console.log (a);} fn (1);//output: Function A () {}, 2

2. There are no block-level scopes in JavaScript, but there are lexical scopes, such as:
Function F1 () {var a=1;f2 ();} function F2 () {return A;} var result = F1 (); Console.log (result);//output: A is not defined
3, within the function without the var keyword declaration variable, the default variable is a global variable, such as:
function Add (A, b) {    var sum = a+b;//Generation sum is a variable inside the Add function and is only used inside the function, and return sum cannot be used outside the function    ;} var result = add; Console.log (result);    3console.log (sum);        Sum is not defined//use the VAR keyword to declare a variable function add (a, b) {    sum = a+b;//The sum of this time is a global variable, and return sum can be called outside of the function    ;} var result = add; Console.log (result);    3console.log (sum);        3
Add: In JavaScript If you do not create a variable, go directly to use, then the error:
12 console.log(xxoo);// 报错:Uncaught ReferenceError: xxoo is not defined
If you create a value without assigning a value in JavaScript, the value is undefined, such as:
123 varxxoo;console.log(xxoo);// 输出:undefined

Within the function, if you write this:

1234567 function Foo(){    console.log(xo);    varxo = ‘seven‘;} Foo();// 输出:undefined

The above code, not error, but output undefined, the reason is: the JavaScript function before it is executed, the variables are all declared, without assigning value. Therefore, the equivalent of the above example, the function in "precompiled" when the Var XO has been executed, so the above code output is undefined.

Note: We usually must pay attention when declaring variables!!! And do not abuse global variables (special attention in the Forin cycle)!!!

4, lexical scope is irreversible, we can see the results from the following example:
Name = Undefinedvar Scope1 = function () {  //name = undefined  var scope2 = function () {    //name = Undefin Ed    var scope3 = function () {      var name = ' Todd ';//locally scoped    };  };};

Before we learned some basic knowledge of scopes, we found that the existence of scopes can save us a lot of things, but at the same time, it also brings us a lot of trouble, for example, we want to call function B in function A below, what should we do?

function A () {
function B () {
//
}
}

Idea: We set a return value for function B, and then call it in function A, the following code:

function A () {    function B () {       console.log ("Hello foodoir!");    }    return B;} var c = A (); C ();//hello foodoir!

So we can get the results we want. In this way, we are basically in the simplest form of closures. Let's go back and analyze the code:

12345 (1)定义了一个普通函数A(2)在A中定义了普通函数B(3)在A中返回B(确切的讲,在A中返回B的引用)(4)执行A(),把A的返回结果赋值给变量 c(5)执行 c()

Summarize these 5 steps into one sentence: function A's intrinsic function B is referenced by a variable C outside of function A. When an intrinsic function is referenced by a variable outside its external function, a closure is formed.

Think: Do we have any other way?

Idea: Using anonymous functions

function A () {    ///anonymous functions    var B = function (x, y) {        return x+y;    }    Console.log (b));//3    return B (+);} var c = A (); Console.log (c);//3

However, in JavaScript high-level programming, the closure "closure refers to a function that has access to variables in another function scope", but we look at an example of an anonymous function, which is obviously not advisable!
This example allows us to better understand closures.

Let's look at some of the following closure Demo1:
function fn () {    var b = "Foodoir";    return function () {        console.log (b);//foodoir        return b;    }} Console.log (b);//b is not definedvar result = FN (); Console.log (Result ());//foodoir
Demo2:
var n;function f () {    var b = "Foodoir";    n = function () {        return B;    }} f (); Console.log (n ());//foodoir
DEMO3:
Correlation definition with closure function f (ARG) {    var n = function () {        return arg;    };    arg++;    return n;} var m = f (123); Console.log (M ());//124//Note that when we return to a function called, arg++ has already performed an increment operation, so M () returns the updated value.
Demo4: Read and modify in a closed packet
The settings in the closure and modify var Getvalue,setvalue; (function () {    var n = 0;    GetValue = function () {        return n;    };    SetValue = function (x) {        n = x;    }}) ();//console.log (n); Console.log (GetValue ());//0console.log (SetValue ());//undefinedsetvalue (123); Console.log ( GetValue ());//123
Demo5: Using closures to achieve iterative results
Implement the iterator effect with        a closure function test (x) {    ///To get an array of internal pointers to the    var i=0;    return function () {        return x[i++];    };} var next = Test (["A", "B", "C", "D"]); Console.log (next ());//aconsole.log (next ());//bconsole.log (next ());// Cconsole.log (Next ());//d
Demo6: Closures in the loop
The closure function in the loop, fn () {    var a = [];    for (Var i=0;i<3;i++) {        A[i] = function () {            return i;        }    }    return A;} var a = fn (), Console.log (A[0] ()),//3console.log (A[1] ()),//3console.log (A[2] ());//3/* * The three closures we created here point to a common local variable i. * But closures do not record their values, they only have a connection to I, so they can only return the current value of I. * Because the value of I at the end of the loop is 3, the three functions point to the common value of 3. * */

Think: How do you make the results output 0, 1, 2, respectively?

Idea one: We can try to use the self-calling function

function fn () {    var a = [];    for (Var i=0;i<3;i++) {        A[i] = (function (x) {            return function () {                return x;            }        }) (i);    }    return A;} var a = fn (); Console.log (A[0] ());//0console.log (A[1] ());//1console.log (A[2] ());//2

Idea two: We localize the I value

function fa () {    function fb (x) {        return function () {            return x;        }    }    var a = [];    for (Var i=0;i<3;i++) {        a[i] = FB (i)    }    return A;} Console.log (A[0] ());//0console.log (A[1] ());//1console.log (A[2] ());//2

------------------------------------------------------Dividing line-------------------------------------------------------


Here, let's take a deeper step into the closure.

We'll extend the demo1 example.

The code examples are as follows:

function Functest () {  var tmpnum=100;//private variable      //Within function Functest/  /define additional function as method of Functest  Innerfunctest (  {       alert (tmpnum);       A temporary variable referencing the outer function functest tmpnum  }      return innerfunctest;//return intrinsic function}    //Call function var myfunctest=functest (); Myfunctest ();//Popup 100

We are more familiar with the concept and usage of closures.

Closures and this related

Closure application example, simulation of the private properties of the class, using the nature of closures, local variables can only be accessed in the Sayage method, and name is accessed externally, thus implementing the private properties of the class.

function User () {    this.name = "Foodoir";  Total attribute    var age = +;    Private attribute    this.sayage=function () {        Console.log ("My is" + age);}    } var user = new User (); Console.log (User.Name); "Foodoir" Console.log (user.age);  "Undefined" user.sayage ();   "My Age is 21"

More in-depth knowledge about closures
In front of the Demo6, we learned that using a self-invoking method to implement closures, we use this approach for more complex operations (writing a simple component).

(function (document) {    var viewport;    var obj = {        init:function (ID) {           viewport = Document.queryselector ("#" +id);        },        addchild:function ( Child) {            viewport.appendchild (child);        },        removechild:function (child) {            Viewport.removechild ( Child);        }    }    Window.jview = obj;}) (document);

The function of this component is to initialize a container and then add a child container to the container, or remove a container. The functionality is simple, but here's another concept: executing functions immediately. Just a quick look at the line. The main idea is to understand how the closure function is implemented in this notation.

Closures are not everything, it has its drawbacks.

1, the closure will make the function of the variables are stored in memory, memory consumption is very large, so can not abuse closures, otherwise it will cause Web page performance problems. In addition, it is possible to trigger a memory leak under IE (memory leak means that when your page jumps, the memory will not be released until your CPU is freed until you close the browser);

2. The closure will change the value of the variables inside the parent function outside the parent function, so don't arbitrarily change the values inside the parent function.

More resources:

JavaScript Advanced Programming (Third Edition), chapter fourth, chapter seventh

JavaScript Object-Oriented Programming Guide Chapter III

Author's words:

This article mainly introduces the scope chain through a few simple examples (by adding several error-prone tips related to the scope chain), and then slowly transitioning to the closure by asking questions (in the case of closures, which describes several common closures), and later on more advanced usage of closures. A good usage of the closures later will continue to be updated.

Closures in JavaScript

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.