ES6 (ii: Variable scope)

Source: Internet
Author: User
Tags anonymous constant valid variable scope wrapper
Let command

First Look at an example

if (true) {
    var a =3;
}
Console.log (a); 3

if (true) {let
    b =3;
}
Console.log (b); REFERENCEERROR:B is not defined

This is the Babel compilation result

if (true) {
    var a = 3;
}
Console.log (a); 3

//Babel declare the block level to a different variable name
if (true) {
    var _b = 3;
}
Console.log (b); REFERENCEERROR:B is not defined

The above code is in the code block, declaring two variables with Let and Var, respectively. These two variables are then called outside of the code block, resulting in a let sound
Variable, var declares that the variable returns the correct value. This indicates that the let declared variable is valid only in the code block where it resides.
For loop counters, it is also appropriate to use the Let command. For () {}

look at a more classic case.

var a =[];

for (var i =0;i<10;i++) {
    A[i] = function () {
        console.log (i);
    }
}
Whether you're here 2 3 4 5 6, the output is the same
a[3] ();//
a[6] ();//10

In fact, we can deal with this situation before we let it. That's the way it seems.

var a =[];

for (var i =0; i<10; i++) {
    (function (i) {//through anonymous function self-tuning
        a[i] = function () {
            console.log (i);
        }
    }) (i)
}
A[3] (); 3
a[6] ();//6

The above code, through an anonymous function self-tuning, the value of I, did a save operation, as for why, the final summary will say.

now let's see the use

var a =[];

For (Let I =0; i<10; i++) {
    A[i] = function () {
        console.log (i);
    }
}
A[3] (); 3
a[6] ();//6

Why does it output so, let's look at the compilation results of Babel

"Use strict";

var a = [];

var _loop = function _loop (i) {//Use a function wrapper
    a[i] = function () {
        console.log (i);
    };
}

; for (var i = 0; i < i++) {
    _loop (i);
}
A[3] (); 3
a[6] ();//6

The above code, in fact, is the same as our handling scheme, which is a function wrapper that saves the variable. (1) There is no variable promotion

Let's look at a statement in advance.

Console.log (a);
var a = 3; Undefined

The above code is actually like this

var A;
Console.log (a);
A = 3; Undefined

In the above code, the variable is promoted to the top of the scope, and the assignment is left locally.

Let's see what we can do .

Console.log (b); REFERENCEERROR:B is not defined let
B = 3;

Babel official compilation results, found that in fact there is a little to read, put it out

"Use strict";

Console.log (b); Undefined
var b = 3;

It feels like a bit of a hole here. (2) temporary Dead zone

As long as a let command exists within a block-level scope, the variable it declares is "bound" to the area and is no longer affected by the external.

var tmp = 123;
if (true) {
    TMP = ' abc ';//referenceerror:tmp is not defined let
    tmp;
}

In the above code, the global variable TMP exists, but the block-level scope let also declares a local variable tmp, which causes the latter to bind the block-level scope, so the TMP assignment will be an error before let declares the variable.

ES6 explicitly states that if a let and a const command exists in a chunk, the variables declared by the block on those commands form a closed scope from the outset.

If you use these variables before the declaration, you will get an error.

In summary, the variable is not available within the code block until the variable is declared with the Let command. This is syntactically called a "temporary Dead zone" (Temporal Dead Zone, abbreviated as TDZ).

PS
In short, the essence of a temporary dead zone is that, as soon as one enters the current scope, the variable to be used already exists, but is not available and can only be obtained and used until the line of code that declares the variable appears. (3) Duplicate declarations are not allowed

Let does not allow the same variable to be declared repeatedly within the same scope.

Function F1 () {let
    a = ten;
    var a = 11; Syntaxerror:identifier ' A ' has already been declared
}
//Error
function F2 () {let
    a = ten;
    let a = 1;
}

Therefore, you cannot re-declare parameters inside a function.

function func (ARG) {let
    arg;//Syntaxerror:identifier ' arg ' have already been declared
}
function func (AR g) {
    let
        arg;//No Error
    }
}
(4) block-level scope

ES5 only the global scope and function scope, there is no block-level scope, which brings a lot of unreasonable scenes.
in the first scenario, the inner variables may overwrite the outer variables.

var tmp = new Date ();
function f () {
    console.log (TMP);
    if (false) {
        var tmp = "Hello World";
    }
} 
f (); Undefined

The code above is actually like this

var tmp = new Date ();
function f () {
    var tmp;
    Console.log (TMP);
    if (false) {
        tmp = "Hello World";
    }
}
f (); Undefined

The above code is actually a common statement ahead of the face of the question, here is involved in the history of JS, before ES6, only the function has scope, if it is inside the function, the declaration will advance the variable declaration to the top of the function, if global, will be promoted to the top of the global scope.

second scenario, the loop variable used to count is leaked as a global variable

var s = ' Hello ';
for (var i = 0; i < s.length; i++) {
console.log (s[i]);
}
Console.log (i); 5

In the above code, the variable i is only used to control the loop, but after the loop is over, it does not disappear and leaks into a global variable.

The block-level scope of the ES6.

Function F1 () {let
    n = 5;
    if (true) {let
        n = ten;
    }
    Console.log (n); 5
}
F1 ();

Babel compilation results are:

"Use strict";

Function F1 () {
    var n = 5;
    if (true) {
        var _n = 10;//old routines, use different variable declarations
    }
    Console.log (n);//5
}
F1 ();

The above function has two blocks of code, all of which declare the variable N and output 5 after running. This means that the outer code block is not affected by the inner block of code. If you use var to define the variable n, the last output value is 10. Because VAR is defined, if is not scoped.

ES6 allows arbitrary nesting of block-level scopes and inner layers to define variables with the same name as the outer layer.

{{{}
    insane = ' Hello world ';
    {Let insane = ' Hello World '}}}
;

Babel compilation results:

{{{{{{}
                var insane = ' Hello world ';
                {
                    var _insane = ' Hello world ';//Old routine.
                }
            }
        }
    }
};
Summary:

(1) Before ES6, the scope is divided into two kinds, one is the global scope, one is the function inner scope, because there is no block-level scope of the concept, the declaration is very easy to pollute the global variable problem.
(2) The appearance of block-level scopes replaces the self-tuning of anonymous functions. Saves the function scope's wording. (5) block-level scopes and function declarations

ES5 states that functions can only be declared in the top-level scope and function scope, not at the block-level scope.

Case one
if (true) {
    function f () {}
}
//Condition two
try {
    function f () {}
} catch (e) {
}

However, the browser does not adhere to this rule, or to support the declaration of functions in the block-level scope, so the above two cases can actually run, no error. However, ES5 "strict mode" will still be an error.

ES6 introduces a block-level scope that explicitly allows functions to be declared within a block-level scope.
And ES6, in the block-level scope, the function declaration statement behaves like let, which is not referenced outside the block-level scope.

function f () {Console.log (' I am outside! ');}
(function () {
    if (false) {
    //} Repeat once function f functions
    f () {Console.log (' I am inside! ');}
    } 
    f ();
} ());

The above code runs in ES5 and gets "I am inside!" because the function f declared within the if is promoted to the function head.

You should avoid declaring functions within a block-level scope, considering that the behavior caused by the environment is too different. If you do, you should write a function expression instead of a function declaration statement.

function declaration Statement
{Let
    a = ' secret ';
    function f () {
        return A;
    }
}
function expression
{let
    a = ' secret ';
    Let F = function () {
        return A;
    };
}

Babel compilation results

' Use strict ';

function declaration statement
{
    var f = function f () {
        return A;
    };

    var a = ' secret ';
}
function expression
{
    var _a = ' secret ';
    var _f = function _f () {
        return _a;
    };
}

In addition, there is a need to pay attention to the place.

The block-level scope of ES6 allows you to declare the rules of a function only if you use curly braces, and if you do not use curly braces, you will get an error. (5) const command

Const declares a read-only constant. Once declared, the value of the constant cannot be changed. Final static similar to Java.
A const declared variable must not change the value, which means.

(1) Once the const declares a variable, it must be initialized immediately, and cannot be left to be assigned later.
(2) The scope of a const is the same as the Let command: it is valid only within the block-level scope where the declaration resides.
(3) The const command declares a constant that is not promoted, and also has a temporary dead zone, which can only be used after the declared position.
(4) Const declaration constants, as well as the Let is not a duplicate declaration.
(5) For a variable of a compound type, the variable name does not point to the data, but instead points to the address where the data resides. The const command simply guarantees that the variable name points to the same address, and does not guarantee that the address's data will not change, so declaring an object as a constant must be very careful.

Give an example to the last point

const FOO = {};
Foo.prop = 123;
123
foo = {};//TypeError: "foo" is read-only

In the above code, the constant Foo stores an address that points to an object.
Immutable is just this address, that is, you cannot point Foo to another address, but the object itself is mutable, so you can still add new properties for it.

Here's another example

Const A = [];
A.push (' Hello '); Executable
a.length = 0;//executable
a = [' Dave '];//Error

In the above code, the constant A is an array, the array itself is writable, but if you assign another array to a, you will get an error.
If you really want to freeze an object, you should use the Object.freeze method.

const FOO = object.freeze ({});
Normal mode, the following line does not work;//Strict mode, the row error
Foo.prop = 123;

In the above code, the constant Foo points to a frozen object, so adding a new property does not work, and the strict mode will also cause an error.
In addition to freezing the object itself, the object's properties should also be frozen. The following is a function that completely freezes an object.

var constantize = (obj) + {
    object.freeze (obj);
    Object.keys (obj). ForEach ((key, value) = {
        if (typeof obj[key] = = = ' object ') {
            constantize (Obj[key]); 
  
   }
    });
};
  

ES5 has only two methods for declaring variables: the var command and the function command.
ES6 In addition to the Let and const commands, the next section mentions two other ways to declare variables: The import command and the Class command. So there are 6 ways to declare variables in ES6.

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.