The let command

  1. ES6 added the let command to declare variables. The usage is similar to var, but the declared variable is only valid within the code block in which the let command resides.

    {
        let a = 1;
        var b = 2;
    }
    console.log(a) // ReferenceError: a is not defined
    console.log(b) // 2
    Copy the code

    The above code uses let and var commands to declare variables respectively in the code block, and calls these two variables outside the code block. The output error of the variables declared by the let indicates that the variables declared by the let cannot be accessed outside the code block.

    The for loop counter is perfectly suited to the let command!

    for (let i = 0; i < 10; i++) {
        console.log(i) // 1 2 3 4 ... 10
    }
        console.log(i) // ReferenceError: i is not defined
    Copy the code

    The counter I in the code above is valid only inside the for loop, and references outside the loop report an error.

    The following is a classic interview question, which can reflect the difference between let and var

    var a = []; for (var i = 0; i < 10; i++){ a[i] = function() { console.log(i); } } a[6](); // 10 ------------------------------------ var a = []; for (let i = 0; i < 10; i++){ a[i] = function() { console.log(i); } } a[6](); / / 6Copy the code

    Why is this the case?

    • When usingvarWhen I is declared, I is globally valid, so there is only one variable I in the world, and the value of I changes every time through the loop, and the function assigned to array A inside the loop outputs I that refers to global I, which means that all the I’s in array A refer to the same I, What causes the runtime to output is the I value of the last round, which is 10.
    • When usingletWhen I is declared, the current I is only valid for this loop, so I is a new variable for each loop, and the final output is 6

    In addition, the for loop has another special feature: the part that sets the variables of the loop is a parent scope, while the inside of the loop body is a separate child scope.

    for (let i = 0; i < 3; i++) {
        let i = 'abc';
        console.log(i); 
    }
    // abc
    // abc
    // abc
    Copy the code

    Run the above code correctly and print ABC three times, indicating that the internal variable I is not in the same scope as the loop variable I!

    1. There is no variable promotion

    The var command will promote the variable. What is variable promotion? Variable promotion refers to the fact that a variable can be called before it is declared, and its value is undefined. In fact, according to general logic, this is a little strange, the normal order would be to declare first and then use. To correct this, the let command changes the syntactic behavior so that variables it declares must be used after they are declared, or an error will be reported!

    console.log(a); // undefined var a = 1; --------------- console.log(b); let b = 2; / / error ReferenceErrorCopy the code

    In the above code, variable A is declared to be promoted with the var command. That is, when the script starts running, variable A already exists but has no value, so undefined is printed. Variable B is declared with the let command and no variable promotion occurs. This indicates that the variable b does not exist before it is declared, and an error will be thrown if it is used.

    1. Temporary dead zone

    As long as the let command exists in the block-level scope, the variables it declares are bound to the scope, no longer subject to external influence!

    var temp = 123;
    if(1) {
        temp = 456; // ReferenceError
        let temp;
    }
    Copy the code

    < span style = “max-width: 100%; clear: both; clear: both; ES6 explicitly states that if there are let and const commands in a block-level scope, the block is initially closed to the variables declared by those commands, and any use of variables before the declaration will result in an error! In short, the variable is not available within the code block until it is declared using the let command. These are grammatically known as “temporal dead zones” (TDZ). Some are hidden and hard to spot.

    function bar(x = y,y = 2) { return [x,y]; } bar(); / / an errorCopy the code

    The above code fails because the default value of parameter x is equal to another parameter y, which is not yet declared and is dead bound.

    ES6 makes it clear that temporary dead zones and let and const statements do not promote variables. The main purpose of ES6 is to reduce runtime errors and prevent the variable from being used before it is declared, resulting in unexpected behavior.

    In short, the essence of a temporary dead zone is that once you enter the current scope, the variable you want to use already exists, but you can’t get it until the line of code that declared the variable appears.

    1. Duplicate declarations are not allowed

    Let does not allow the same variable to be declared twice in the same scope

    Function () {let a = 10; var a = 1; Function () {let a = 10; let a = 1; } function func(arg) {let arg; } function func(arg) {{let arg; // Normal}}Copy the code

    Block-level scope

    1. Why do you need block-level scopes

    ES5 has only global and functional scopes, not block-level scopes, which makes many scenarios irrational. In the first scenario, the inner variables may override the outer variables.

    var temp = new Date();
    function f() {
        console.log(temp);
        if(false){
            var temp = 'abc';
        }
    }
    f(); // undefined
    Copy the code

    In the second scenario, loop variables used to count are exposed as global variables.

    var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); / / 5Copy the code

    In the code above, variable I is used only to control the loop, but when the loop ends, it does not disappear, but leaks out as a global variable.

    1. ES6 block-level scope

    Let actually adds block-level scope to JavaScript.

    function fn() {
        let n = 5;
        if(true) {
            let n = 10;
        }
        console.log(n); // 5
    }
    Copy the code

    In the code, two variables n belong to different blocks, and only the variable in the same block will be printed. If variable n is declared with var, the output result will be 10. Block-scoped travel virtually eliminates the need for the widely used execute anonymous function (IIFE) immediately!

    1. Block-level scopes and function declarations

    Did you know that declaring functions like this is actually illegal in ES5:

    If (true) {function f () {}} try {function f () {}} catch (e) {}Copy the code

    If you type the code into the compiler, you will find that the browser will actually run without any errors, because the browser does not comply with this rule. In order to be compatible with older code, it still supports the declaration of functions in the block level scope.

    Block-level scopes were introduced in ES6, explicitly allowing functions to be declared in block-level scopes. ES6 states that function declaration statements behave like lets in block-level scope and cannot be referenced outside the block-level scope!

    Const command

    1. Basic usage

    Const declares a system constant. Once declared, its value cannot be changed.

    Const PI = 3.1415; console.log(PI); // 3.1415 PI = 3; // Assignment to constant variable.Copy the code

    Indicates that changing the value of a constant will cause an error!

    Constants declared by const may not change their value. This means that const, once declared, must be initialized immediately and cannot be left to be assigned later. Declaring a constant without assigning it also raises an error.

    Const has the same scope as the let command: it cannot be repeated, is valid only in the block-level scope in which it is declared, declared constants are not promoted, and there is also a temporary dead zone that can only be used after the declaration.

    1. nature

    What const actually guarantees is not that the value of the variable is fixed, but that the memory address to which the variable points is fixed. For simple data types (values, strings, booleans), the value is stored at the memory address the variable points to because it is equivalent to a constant. But for complex data (mainly objects and arrays), variable pointing to save memory address is a pointer, const can guarantee the pointer is fixed, as far as it is pointing to the data structure of variable, it can’t control, therefore, to declare an object as a constant when must be very careful.

    const foo = {}; // Add an attribute to foo, which succeeds foo.prop = 123; // point foo to another object, foo = {}; // TypeError:"foo" is read-onlyCopy the code

    Foo above stores an address that points to an object. The address is immutable, that is, you cannot point foo to another address, but the object itself is mutable, so you can still add new properties to it.

    const a = []; a.push('Hello'); // can be a.length = 0; // a = ['Dave']; / / an errorCopy the code
    1. ES6 6 ways to declare variables
    • There are only two ways to declare variables in ES5:varCommands andfunctionCommand.
    • ES6 in addition to addletandconstOrders, andimportCommands andclassThe command

    Properties of the top-level object

The top-level object refers to the Window object in the browser environment and the Global object in the Node environment. In ES5, attributes of top-level objects are equivalent to global variables.

Properties of top-level objects that are related to global variables are considered one of the biggest design failures in the JavaScript language. There are several big problems with this design:

  • Undeclared errors in variables cannot be prompted at compile time, only known at run time
  • It’s easy to unknowingly create global variables (such as typos) during development
  • The properties of top-level objects are accessible everywhere, making modular programming very difficult
  • The window object has an entity meaning and refers to the browser window object

To sum up, this design mode is not quite appropriate. In ES6, global variables declared by var and function commands are still attributes of top-level objects, while global variables declared by let, const, and class commands are not attributes of top-level objects.

var a = 1; A console.log(window.a); // 1 let b = 1; console.log(window.b); // undefinedCopy the code