JavaScript from scope to closure

Source: Internet
Author: User

Scope (Scope) global scope and local scope

Generally speaking, this is a distinction between global variables and local variables. Reference citation: JavaScript Development Advanced: Understanding JavaScript scopes and scope chains

Global scope: The outermost function and the variables defined outside the outermost function have global scope.

1) The outermost function and the variables defined outside the outermost function have global scope

2) All variables that are directly assigned to the definition are automatically declared to have global scope, that is, variables that are not declared with VAR are global variables, and are properties of the top-level object.

3) All Window object properties have global scope

Local scope: In contrast to the global scope, local scopes are generally accessible only within a fixed code fragment, most commonly such as inside a function, so in some places it is also seen that this scope is called a function scope.

Please refer to the citation for the Code section.

block scope and function scope

The function scope is interpreted relative to the block scope, and its local scope is a meaning. Reference citation: Conceptual understanding of scope and block-level scope of JavaScript

Block scope: Any set of statements in a pair of curly braces {} belongs to a block, and all variables defined in it are not valid outside the code block, which we call a block-level scope.

function scope: Parameters and variables in a function are inaccessible outside of the function. The scope of JavaScript is lexical in nature (lexically scoped). This means that the function runs in the scope that defines it, not in the scope in which it is called. This is explained below.

View Code

Running this code will cause "use of an undefined variable:j" error. As you can see, the C language has a block-level scope because J is defined in the IF statement block, so it is inaccessible outside the block.

View Code

Run this code, pop up "3", visible, outside the block, the variable I defined in the block can still be accessed. In other words, JS does not support block-level scopes, it supports only function scopes, and variables defined anywhere in a function are visible anywhere in the function.

declaration in scope is in advance
var scope= "global";  global variable function t () {      console.log (scope);      var scope= "local";//local variable    console.log (scope);              }  T ();

(Console.log () is the console's debugging tool, Chrome is called to check, and some browsers are called censorship elements, alert () Pop-up window will break the page effect)

The first sentence output is: "Undefined", not "global"

The second output is: "Local"

The second, needless to say, is the local variable output "local". The first reason is also "local", because the declaration in JS in advance, although the Declaration and assignment of local variables in line 4th, but in fact, the declaration of the 4th Line is advanced, placed on the top of the function body, and then on the 4th row of the local variable assignment. It can be understood as follows.

var scope= "global";//global variable function t () {    var scope;//local variable declaration    Console.log (scope);    Scope= "local";//local variable assignment    console.log (scope);} T ();

Specific details can be found in the Rhino Book (The JavaScript authoritative guide) in detail.

Scope Chain ( Scope Chain )

When code executes in an environment, a scope chain of variable objects is created (scope chain). The purpose of a scope chain is to ensure an orderly access to all variables and functions that the execution environment has access to. The front end of the scope chain, which is always the variable object for the environment in which the code is currently executing. If the environment is a function, its active object is used as a variable object. Reference citation: JS scope and scope chain, an analysis of the scope chain –JS Foundation core

Num= "one"; var a = 1;  The local scope of function t () {  //t functions, which can access a B variable, but not the C variable     var num= "a";      var b = 2;    function A () {//a functions local scope, can be accessed to the A,B,C variable         var num= "three";//local variables with external variables with local variables mainly        var c = 3;        Console.log (num); Three     } function      B () {  //b functions local scope, access to A/b variable, access to C variable        console.log (num);//two    }
   a ();      B ();  }  T ();

When you execute a, you create the execution environment (the calling object) of function A, place the object at the beginning of the list, and then link the calling object of the function T to the next, and finally the global object. Then look for the variable num from the beginning of the list.

namely: A ()->t ()->window, so num is "three";

However, when B () is executed, the scope chain is: B ()->t ()->window, so num is "one";

In addition, there is a special example I think should be sent. Using the scope of JavaScript is lexical (lexically scoped). This means that the function runs in the scope that defines it, not in the scope in which it is called. This sentence explains the following example.

var x = 10;function A () {console.log (x);} Function B () {var x = 5;a ();} b ();//Output is 10

Although the B function calls a, but a is defined under the global scope, it is also running under the global scope, so its internal variable x looks up to the global variable x=10, so the output of the B function is 10;

For a deeper explanation, refer to: JavaScript Development Advanced: Understanding JavaScript scopes and scope chains.

Classic Case

Here is an example of a classic event binding:

<div id = "Test" >    <p> column 1</p>    <p> column 2</p>    <p> column 3</p>    < p> column 4</p></div> </body><script type= "text/javascript" >    function Bindclick () {    var ALLP = document.getElementById ("Test"). getElementsByTagName ("P"),    i=0,    len = allp.length;            for (; i<len;i++) {    Allp[i].onclick = function () {        alert ("You click the" +i+ "P tag!"); /you Click the 4 P tag!        }}}    Bindclick ();//Run function, Bind-point-click event </script>

The above code adds a click event to the P tag, but no matter which p tab we click, the result we get is "you click the 4 P tag!".

We can JS break down the above code to make it look easier to understand, as shown below. The previous use of an anonymous function as the click callback function of the event, where a non-anonymous function is used, as a callback, the exact same effect.

function Bindclick () {    var allp = document.getElementById ("Test"). getElementsByTagName ("P"),    i=0,    len = Allp.length;    for (; i<len;i++) {    Allp[i].onclick = ALERTP;    }    function Alertp () {    alert ("You click the" +i+ "P tag!");}    } Bindclick ();//Run function, bind a point-click event

There should be no problem here, the previous use of an anonymous function as click the callback function of the event, a non-anonymous function used here, as a callback, the exact same effect. You can also do the next Test Oh.

Understanding the above, then it can be very simple to understand why our previous code, will get the same result. First look at the for loop, here we just add a callback function for each matching element click , and the callback function is a AlertP function. Here, when you add a success to each element, click i The value becomes the number of matching elements, that is, when we trigger the event, that is, when we click on the i=len corresponding element, we expect that the element we clicked is arranged in the first line. When the click event is triggered, the callback function is executed, AlertP but when it is executed here, one of the alert variables in the discovery method is unknown, and in AlertP the local scope, and no corresponding variable is found, then by the way the scope chain is looked up, the parent scope is searched. , there is a variable in the parent scope, i and the value of I is the for value after the loop i=len . So there was the effect that we initially saw.

The workaround is as follows:

function Bindclick () {    var allp = document.getElementById ("Test"). getElementsByTagName ("P"),
I=0,
len = allp.length; for (; i<len;i++) { ALERTP (allp[i],i); } function ALERTP (obj,i) { Obj.onclick = function () { alert ("You click the" +i+ "P tag!");}} } Bindclick ();

Here, obj and i AlertP inside the function, is the local variable. clickthe callback function of the event, although there is still no i value of the variable, but its parent scope AlertP of the internal, but there is a normal display, where AlertP I put in the bindClick interior, just because this can reduce the necessary global functions, and put to the global also does not affect.

Here is the addition of a function to bind, if I do not want to add a function, of course, can also be implemented, here is the self-executing function. You can jump to the self-executing function of this article, or you can see the in-depth explanation of the reference citation: An analysis of the scope chain –JS Foundation core

function declaration and assignment declarative functions, assignment functions, and anonymous functions

Anonymous functions: Function () {}; Declaring a function with the function keyword, but not naming it, is called an anonymous function, which has many functions, assigning a variable to create a function, assigning an event to an event handler or creating a closure, and so on. We'll talk about it later.

The function definition in JS is divided into two kinds: declarative function and Assignment function.

<script type= "Text/javascript" >FN (); Execution result: "Declarative function executed", the function is declared and processed during the pre-compilation period, so even if the FN () call function is placed before the function is declared, it can be executed. function Fn () {//Declarative function alert ("declared function executed");} </script>
<script type= "Text/javascript" >FN (); Execution result: "FN is not a function" var Fn = function () {//Assignment function alert ("performed an assignment function");} </script>

The parsing process of JS is divided into two stages: pre-compilation period (preprocessing) and execution period.
Pre-compile time JS will handle all declared variables and functions in this code block (similar to C language compilation), at this time the function is only a declarative function, and the variable is only declared (declaration in advance) but not initialized and assignment. That's why there are two cases.

When normal, function calls are declared, and functions with the same name override the former.

<script type= "Text/javascript" >function Fn () {//Declarative function alert ("declared function executed");} var Fn = function () {//Assignment function alert ("performed an assignment function");} Fn ();//Execution Result: "An assignment function is executed", the same name function will overwrite the former </script>

Similarly, when declaring a function in advance, there is also the case of a function overlay with the same name.

  code block

Code blocks in JavaScript refer to snippets of code that are split by <script> tags. JS is compiled and executed according to blocks of code, and blocks are independent of each other, but variables and methods are shared. As follows:

<script type= "Text/javascript" >//code block one var test1 = "I am code block one test1"; alert (str); because there is no STR defined, the browser will go wrong and the following cannot run alert ( "I am code block One");//did not run to here var test2 = "I am a block of code test2";//not run here but the pre-compilation link is declared in advance, so there is a variable but not assigned value </script><script type= "text/ JavaScript ">//code block two alert (" I am code block two "); Here there are running to alert (test1); pops up "I'm code block one test1" alert (test2); Pop-up "undefined" </script>

code block one in the above code to run an error, but does not affect the execution of code block two, which is the code block between the independence, and code block two can be called to code one of the variables, it is the inter-block sharing.

However, when the first block of code stops, it does not affect the next block of code to run. Of course, in the following example, although the function declaration in block two is precompiled, the function in code block 1 appears with the FN function as the definition error (the browser error, not the declared unassigned undefined), stating that code block 1 executes the code block 2 after it is fully executed.

<script type= "Text/javascript" >//code block 1Fn (); Browser error: "Undefined", stop code block 1 run alert ("code block 1 executed");//Not run </script><script type= "Text/javascript" >// Code block 2alert ("code block 2 executed");//Perform a bullet box effect function Fn () {//function 1alert ("performed function 1");} </script>
So the JS function parsing sequence is as follows:
Step 1. Read into the first block of code.
Step 2. Do grammar analysis, error is reported grammatical errors (such as parentheses mismatch, etc.), and jump to step5.
Step 3. "Precompiled processing" of var variables and function definitions (never error, because only the correct declarations are parsed).
Step 4. Execute code snippet, error (e.g. variable undefined).
Step 5. If there is a next code snippet, read the next code snippet and repeat the Step2.
Step6. End. Note: The JS code that needs to be executed before the page element is rendered should be placed in the <script> code block in front of <body>, but after the page element is loaded, JS is placed behind the </body> element. The onload event of the body tag is executed at the end.
<script type= "Text/javascript" >alert ("first"), function Fn () {alert ("Third");} </script><body onload= "Fn ()" ></body><script type= "Text/javascript" >alert ("second"); </ Script>
self-executing functions

That is, by adding parentheses after the function name, the function will execute itself. When binding an event, beginners like me sometimes make the following error, Window.onclick = AB (), so that the function AB executes at first. The correct approach should be to remove the brackets after the AB. This parenthesis is actually the result of the operation of the AB function is assigned to the Click event.

The following two examples clearly reflect the situation after the function is assigned.

1:

function ab () {    var i=0;    Alert ("AB");    return i;} var c=ab ();//Execute AB function alert (typeof c+ "      " +c);//number  0

2:

function ab () {    var i=0;    Alert ("AB");    return i;} var c=ab;//only assigns alert (typeof c+ "      " +c),//function  function ab () {var i=0;alert ("AB"); return i;}

Note: However, this function must be a function expression (such as the above-mentioned assignment function) and cannot be a function declaration. For details, see: JS Execute function immediately: (function () {...}) () with (function () {...} ())

The paper mainly talks about the self-executing method of anonymous function, which is added in front of functions! , +,-even a comma wait for the effect to be executed immediately after the function definition, and (),! , + 、-、 =, and so on, all function declarations are converted into function expressions , eliminating the ambiguity of the JavaScript engine recognition function expressions and function declarations, telling the JavaScript engine that this is a function expression, not a function declaration, you can add parentheses later, And immediately executes the code of the function (this is the method used by JQ). An example is shown below.

(function (a) {    console.log (a);   Firebug output 123, using () operator}) (123);  (function (a) {    console.log (a);   Firebug output 1234, using () operator} (1234));  ! function (a) {    console.log (a);   Firebug output 12345, use! operator} (12345);  +function (a) {    console.log (a);   Firebug output 123456, using the + operator} (123456);  -function (a) {    console.log (a);   Firebug output 1234567, using-operator} (1234567);  var fn=function (a) {    console.log (a);   Firebug output 12345678, using = operator} (12345678)

The function is to implement the block scope.

The concept of a private scope in JavaScript, if you declare some variables in a global or local scope on a multi-person project, may be overridden by someone else accidentally with a variable of the same name, depending on the nature of the scope chain of the JavaScript function, Using this technique, you can imitate a private scope, use an anonymous function as a "container," inside the "container" to access the external variables, and the external environment cannot access the variables inside the "container", so (function () {...}) () internally defined variables do not collide with external variables, commonly known as "anonymous wrapper" or "namespace." The code is as follows:

function Test () {(function () {for (Var i=0;i<4;i++) {}}) (); alert (i);//Browser error: I is not defined} test ();

You can compare the code that was introduced at the beginning of the scope.

closures (Closure)

Closures are difficult for beginners, need to learn a lot to understand, so the scope of the chain and the knowledge of anonymous functions as a foreshadowing. My closures here are based on the basics and may post some more core content later. I refer to the explanations of the great gods here. Reference citation: Learn JavaScript closures (Closure), JavaScript anonymous functions (anonymous function) and closures (Closure), an analysis of the scope chain –JS one of the fundamental core

Closures are functions that can read the internal variables of other functions, so in essence a closure connects the inside of the function to the outside of the function.

Closures are variables or methods inside a function that can be referenced by other methods after the execution of the function ends and the scope chain pops up the function.

Two useful: One can read the variables inside the function, and the other is to keep the values of these variables in memory at all times.

To help understand, I looked for a few examples:

1. (Nanyi Teacher's explanation)

Function F1 () {var n=999;    Nadd=function () {n+=1} function F2 () {alert (n);  } return F2;  } var result=f1 (); Result ();  999 Nadd (); Result (); 1000

In this code, result is actually the closure F2 function. It runs altogether two times, the first value is 999, the second value is 1000. This proves that the local variable n in the function F1 is kept in memory and is not automatically cleared after the F1 call.

Why is that? The reason is that F1 is the parent function of F2, and F2 is assigned to a global variable, which causes F2 to always be in memory, and F2 's presence depends on F1, so F1 is always in memory and will not be reclaimed by the garbage collection mechanism (garbage collection) after the call ends.

Another notable part of this code is the line "nadd=function () {n+=1}", which first did not use the var keyword in front of Nadd, so Nadd is a global variable, not a local variable. Second, the value of Nadd is an anonymous function (anonymous functions), and the anonymous function itself is a closure, so nadd is equivalent to a setter that can manipulate local variables inside the function outside of the function.

2. (A great God)

function foo () {var a = ten; function bar () {a *= 2; return A;} return bar;} var baz = foo (); Alert (Baz ()); 20alert (Baz ()); (    Baz ());//80var Blat = foo (); alert (Blat ());//20

You can now access a from outside;
A is running in the Foo that defines it, rather than running in the scope that calls Foo. As long as bar is defined in Foo, it can access the variable a defined in Foo, even if the execution of Foo has ended. In other words, when the "var baz = foo ()" is executed, Foo is finished and a should not exist, but then called Baz Discovery, a still exists. This is one of the JavaScript features--run the call in the definition, not the run.
where "var baz = foo ()" is a reference to a bar function; "Var blat= foo ()" is another bar function reference.
The closure can also be used to implement private members, but I do not understand, so I do not post it, want to see the reference citation: JavaScript anonymous functions (anonymous function) and closure (closure).

End

The first time you write such a long article, most of it is quoted, but all the content is to practice and think about it before the post, as a beginner may have explanations and inappropriate references, please also point out. There are problems in the place also please teachers and students to discuss more.

Thanks again to all citation authors, the growth of knowledge lies in communication, thanks to the hard communicators.

JavaScript from scope to closure

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.