JavaScript scope and scope chain explanation, declaration promotion

Source: Internet
Author: User
Tags closure lua variable scope

I'm sure you'll be confused about the scope, scope chain, and variable declaration promotion concepts when you get started with JavaScript.

Javascript Scopes

In Javascript, there are only local scopes and global scopes. Instead, only functions can create local scopes, such as if,for or while block statements are not able to create scopes. (Of course ES6 provides the LET keyword to create a block scope.) )

This feature of Javascript causes unexpected results when creating closures within a for loop. For example, the following:

var i =20;var Makelogger = function ( {var Funcs = []; for (var i = 0; i < 10; ++i) {Funcs[i] = function ( Span class= "Hljs-params")  {console.log (i);}} return Funcs;} var loggers = Makelogger (); for (var i = 0; i < 10; ++i) {Loggers[i] (),}               

RESULTS:

The above output, the approximate reason is that the scope of the variables inside the for loop is the entire function, a series of closures created inside the loop refers to the same variable I, and at the end of the for loop, the value of this I becomes 10. So when we call these intrinsics, we're going to output 10.

This may not be clear enough now, and it's easier to understand when we understand how the scope chain and Javascript are performing.

Javascript Scope Chain
    1. When a function is declared inside Js, a scope property is created for the function object that points to the current scope chain object.
    2. When a function is called in Js, an execution context is created, which defines the environment information when the function interprets execution. Each execution context has its own scope chain, which is used primarily for parsing variable identifiers.
    3. When the Js engine runs a function, it first adds the scope property of the function to the scope chain of the execution context, and then creates an active object added to the top of the scope together to form a new scope chain. The active object contains all the formal parameters of the function, the arguments object, all the local variable variables, and so on.
    4. When interpreting each statement of a function, the identifier is looked up according to the scope chain of the execution context, and if no identifier is found above a scope object, it is looked up along the chain of action, similar to the property lookup mechanism inherited by Js's prototype.

Let's look at a few specific examples:

' Zilongshanren ';  functionecho()console.log (name);} Echo ();    

RESULTS:

Undefinedhello

To understand the output of the above code, we can explain it in terms of the 4 points mentioned above:

    • When declaring the Echo function, the scope chain at this time is (we assume that scope chain is an array of scope objects)
[[scope chain]] = [{     global Object: {          ' Zilongshanren '          ...     }}]

The scope property of the Echo function points to this scope chain object.

    • When the Echo function is called, an execution context is created, and the scope of the ECHO is added to the scope chain of the execution context. Create an active object at the same time and add it to the top of the scope chain. The scope chain at this time is:
[[scope chain]] = [{    Active Object {         name:undefined,         arguments: ...         ...    },     global Object: {          ' Zilongshanren '          ...     }}]
    • When the first statement of the execution function is interpreted, the name variable is found in the active object, and the output is undefined. Then execute var name = ' Hello ', at which point the value of the variable name is hello. The last explanation for executing console.log (name) is the output of hello.

This example may be easier because it does not use closures.

Let's break down the example at the beginning of this article.

    • When defining the Makelogger function, the scope of the Makelogger function is:
[[scope chain]] = [{     global Object: {...               }}]
    • When defining a closure function within a for loop, the scope chain at this time is:
[[scope chain]] = [{     local scope object: {        i:undefined,        funcs: [],     },     Global object: {
     
       >
                ...     }] 
     

And at this point the scope of Funcs...funcs points to the scope chain.

    • When the Makelogger function is called, an execution context is created. Add the scope chain of the Makelogger function to the execution context, and create an active object to the top of the scope chain at which scope chain:
[[scope chain]] = [{     Makelogger active object: {          funcs:undefined,          i:undefined,          arguments: ...     },< C6/>global Object: {...               }}]
    • When the Makelogger function is executed, the scope object at this time becomes:
[[scope chain]] = [{     local scope object: {        i:undefined,        funcs: [object ...],     },     C22>i:20, ...}]  

The Funcs function here also generates a closure object that contains the value of the variable Makelogger local scope, which is i=10.

is the Funcs function and its closure in the V8 engine:

    • At the end of the loop, when all loggers are executed, an execution context is created for each loggers function in turn, with the scope chain for each execution context:
[[scope chain]] = [{     object: {         argument, funcs: [Global objec20, ...}} ]

When the Console.log (i) of the loggers function is executed, the variable is searched along the scope chain at this time, and the i=10 is found. So the result of our output is 10.

Variable Promotion

Let's look at an example:

' Zilongshanren ';  functionecho()console.log (name);} Console.log (name); Echo ();     

+results:

zilongshanrenhellohelloundefined

Instead of re-assigning the global variable name to the first line of the echo function, name = "Hello", the variable name declared inside the function is assigned a value. So, after the Echo function declaration, the Console.log (name) output or Zilongshanren is called.

The name variable inside the echo function is "used before, and declared in the back", which is called the variable promotion.

It would be easier to understand this behavior from the variable scope and scope chain we mentioned earlier.

Because of the "elevated" side effects of variable declarations inside a function, it is best to place the local variables that the function needs to be declared at the beginning of the function to avoid unnecessary confusion.

Summary

The functions in JavaScript run in the scope they are defined, not in the scope in which they are executed. Understanding scope and scope chains can be very helpful in understanding the wonderful features of closures and variable promotion. This article may not be very clear in some places, readers can read the back of the reference link, I believe it will help understand.

JavaScript scope and scope chain explanation, declaration promotion

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.