let / const and block-level scope

This series is the usual reading, learning, real-world projects have new features on es6 in, with a brief summary of the hair, the purpose is to record for later review; this series is expected to contain let / const, arrows function, deconstruction, new common method, Symbol, Set & Map, Proxy, reflect, Class, Module, Iterator, Promise, Generator, async / await

let / const brought us what?

let

  1. Bound variable lift
    (function foo() {
            console.log(a);
            let a = 1;
        })();
    
    // Uncaught ReferenceError: a is not defined

    To conclude that one: Before variables, we must first declare the variable declaration always before use.

  2. It brought the block-level scope
    Copy the code
    // es5
        (function(){
            if(false) {
                var temp = 1;
            }
            console.log(temp); // undefined
        })();
    
        // es6
        (function(){
            if(false) {
                let temp = 1;
            }
            console.log(temp); // Uncaught ReferenceError: temp is not defined
        })();
    Copy the code

    From the code, we can clearly see let's es6 of block-level scope, the block-level scope What application do? for example:

    Copy the code
    var fnArr = [];
        for(var i = 0; i < 5; i++) {
            fnArr.push(function() {
                console.log(i);
            });
        }
        fnArr[0](); // 5
        fnArr[1](); // 5
        fnArr[2](); // 5
        fnArr[3](); // 5
        fnArr[4](); // 5
        console.log(i); // 5
    Copy the code

    Without careful analysis, the results of the implementation is not surprising that some of it? Yes, we intended for internal use in variable loop i was leaked became a global variable, and each cycle of the for loop, the variable i has not been restated, virtually every function stored in an array referenced fnArr They are the same variable i, so that led to the current results, how to make the code run in accordance with our initial ideas? Es5 commonly used term solution

    Copy the code
    var fnArr1 = [];
        for(var i = 0; i < 5; i++) {
            (function(j) {
                fnArr1.push(function() {
                    console.log(j);
                });
            })(i)
        }
        fnArr1[0](); // 0
        fnArr1[1](); // 1
        fnArr1[2](); // 2
        fnArr1[3](); // 3
        fnArr1[4](); // 4
        console.log(i); // 5
    Copy the code

    Appears to be solved, here actually used the method closure, fnArr1 function references in each of j is a copy of the current time cycle i, thus solves the previous problem, but there is a problem: Variable i still get leaked to the implicit global

    Copy the code
    var fnArr1 = [];
        for(let i = 0; i < 5; i++) {
            fnArr1.push(function() {
                console.log(i);
            });
        }
        fnArr1[0](); // 0
        fnArr1[1](); // 1
        fnArr1[2](); // 2
        fnArr1[3](); // 3
        fnArr1[4](); // 4
        console.log(i); // Uncaught ReferenceError: i is not defined
    Copy the code

    OK, problem solved, will only be replaced with let 'var', which is let the convenience.

  3. Prohibition of temporary dead zone & repeat statement
    Copy the code
    // What is prohibited declared repeatedly it? To not give a written explanation, a look often wording ES5 
    ( function () {
             var TEMP =. 1 ;
             var TEMP = 2 ;
             var TEMP = function () {
                 return . 1 ; 
            }; 
        }) ();
    Copy the code

    The above code execution without any problems, final temp is assigned a function

    Copy the code
    (function() {
            let temp = 1;
            var temp = 2; // Uncaught SyntaxError: Identifier 'temp' has already been declared
            var temp = function() {
                return 1;
            };
        })();
    Copy the code

    In the third row will throw an error: temp has been declared, yes, let the variables declared, the declaration is not allowed again, to give a few examples of consolidating:

    Copy the code
    (function() {
            var temp = 2;
            var temp = function() {
                return 1;
            };
            let temp = 1; // Uncaught SyntaxError: Identifier 'temp' has already been declared
        })();
    
        (function() {
            if(true) {
                let temp = 1;
                var temp = 2; // Uncaught SyntaxError: Identifier 'temp' has already been declared
            }
        })();
    
    (function() {
            if(true) {
                let temp = 1;
                function temp() { // Uncaught SyntaxError: Identifier 'temp' has already been declared
                    return 1;
                }
            }
        })();
    Copy the code

    See out of it? As long as the scope let declaration occurs, it is not permitted to declare variables with the same name again (including the function declaration)

    var foo = 1;
        if(true) {
            foo = 2; // Uncaught ReferenceError: foo is not defined
            let foo;
        }

    Let's see 'high-handed', right? As long as the scope let where the variable of the same name will be occupied let, not allowed to repeat the statement, but also let's follow the rules

  4. Global variables are no longer as properties of the window object
    var foo = 1;
        (function() {
            bar = 2;
        })();
        window.foo; // 1
        window.bar; // 2

    Yes, es5, the global variables (including the accidental leakage) will automatically be added as properties of the window object

    let foo = 1;
        
    window.foo; // undefined

    it is more than words. . .

const

  1. let owned properties, const has, at the same time there is a const: const declared variables must be initialized, and can not be reassigned
    const temp = 1;
        temp = 2; // Uncaught TypeError: Assignment to constant variable.

    Note that can not be reassigned, this is more accurate, in fact, declared const variables can be modified when the variable is initialized to declare const complex data types, variables declared const is variable, as to why he understand myself (variable identifier stored in complex data types only memory address it ...)

    TEMP = const {}; 
        temp.foo = 'AA'; // this is no problem 
        TEMP = {foo: 'AA'}; // this will throw an exception

     

Variable declaration for the cycle

When recording let the front block-level scope, we used an example of a for loop, here we might as well try to resolve what for loop execution

Copy the code
var fnArr = [];
    for(var i = 0; i < 3; i++) {
        fnArr.push(function() {
            console.log(i);
        });
    }

    // 伪代码
    var fnArr;
    fnArr = [];
    {
        var i;
        i = 0;

        if(i < 3) {
            fnArr.push(function() {
                console.log(i);
            })
        }
        i++;
        if(i < 3) {
            fnArr.push(function() {
                console.log(i);
            });
        }
        i++;
        ...
    }
Copy the code

Unfortunately, there was clear all i see is a i. . . After that let it use?

Copy the code
var fnArr = [];
    for(let i = 0; i < 3; i++) {
        fnArr.push(function() {
            console.log(i);
        });
    }

    // 伪代码
    var fnArr;
    fnArr = [];
    {
        let i;
        i = 0;

        if(i < 3) {
            let i = i;
            fnArr.push(function() {
                console.log(i);
            })
        }
        i++;
        if(i < 3) {
            let i = i;
            fnArr.push(function() {
                console.log(i);
            });
        }
        i++;
        ...
    }
Copy the code

Is not see the point of tricks? In fact, we can understand, in each cycle are re-declare i, and i is assigned to the outer layer of the current value. (Note that ah, here is pseudo-code, easy to understand, in practice let i = i will throw exceptions)

Reprinted Source: https://www.cnblogs.com/innooo/p/10438947.html

This series is the usual reading, learning, real-world projects have new features on es6 in, with a brief summary of the hair, the purpose is to record for later review; this series is expected to contain let / const, arrows function, deconstruction, new common method, Symbol, Set & Map, Proxy, reflect, Class, Module, Iterator, Promise, Generator, async / await

let / const brought us what?

let

  1. Bound variable lift
    (function foo() {
            console.log(a);
            let a = 1;
        })();
    
    // Uncaught ReferenceError: a is not defined

    To conclude that one: Before variables, we must first declare the variable declaration always before use.

  2. It brought the block-level scope
    Copy the code
    // es5
        (function(){
            if(false) {
                var temp = 1;
            }
            console.log(temp); // undefined
        })();
    
        // es6
        (function(){
            if(false) {
                let temp = 1;
            }
            console.log(temp); // Uncaught ReferenceError: temp is not defined
        })();
    Copy the code

    From the code, we can clearly see let's es6 of block-level scope, the block-level scope What application do? for example:

    Copy the code
    var fnArr = [];
        for(var i = 0; i < 5; i++) {
            fnArr.push(function() {
                console.log(i);
            });
        }
        fnArr[0](); // 5
        fnArr[1](); // 5
        fnArr[2](); // 5
        fnArr[3](); // 5
        fnArr[4](); // 5
        console.log(i); // 5
    Copy the code

    Without careful analysis, the results of the implementation is not surprising that some of it? Yes, we intended for internal use in variable loop i was leaked became a global variable, and each cycle of the for loop, the variable i has not been restated, virtually every function stored in an array referenced fnArr They are the same variable i, so that led to the current results, how to make the code run in accordance with our initial ideas? Es5 commonly used term solution

    Copy the code
    var fnArr1 = [];
        for(var i = 0; i < 5; i++) {
            (function(j) {
                fnArr1.push(function() {
                    console.log(j);
                });
            })(i)
        }
        fnArr1[0](); // 0
        fnArr1[1](); // 1
        fnArr1[2](); // 2
        fnArr1[3](); // 3
        fnArr1[4](); // 4
        console.log(i); // 5
    Copy the code

    Appears to be solved, here actually used the method closure, fnArr1 function references in each of j is a copy of the current time cycle i, thus solves the previous problem, but there is a problem: Variable i still get leaked to the implicit global

    Copy the code
    var fnArr1 = [];
        for(let i = 0; i < 5; i++) {
            fnArr1.push(function() {
                console.log(i);
            });
        }
        fnArr1[0](); // 0
        fnArr1[1](); // 1
        fnArr1[2](); // 2
        fnArr1[3](); // 3
        fnArr1[4](); // 4
        console.log(i); // Uncaught ReferenceError: i is not defined
    Copy the code

    OK,问题解决了,仅仅是将’var‘替换成了let,这就是let带来的便利。

  3. 产生暂时性死区&禁止重复声明
    Copy the code
    // 什么是禁止重复声明呢? 先不给书面解释,来看一个es5中经常的写法
    (function() {
            var temp = 1;
            var temp = 2;
            var temp = function() {
                return 1;
            };
        })();
    Copy the code

    上面这段代码执行没有任何问题,最终temp被赋值为一个函数

    Copy the code
    (function() {
            let temp = 1;
            var temp = 2; // Uncaught SyntaxError: Identifier 'temp' has already been declared
            var temp = function() {
                return 1;
            };
        })();
    Copy the code

    在第三行时就抛出了一个错误:temp已经被声明,是的,let声明过的变量,是不允许再次被声明的,再给几个例子巩固一下:

    Copy the code
    (function() {
            var temp = 2;
            var temp = function() {
                return 1;
            };
            let temp = 1; // Uncaught SyntaxError: Identifier 'temp' has already been declared
        })();
    
        (function() {
            if(true) {
                let temp = 1;
                var temp = 2; // Uncaught SyntaxError: Identifier 'temp' has already been declared
            }
        })();
    
    (function() {
            if(true) {
                let temp = 1;
                function temp() { // Uncaught SyntaxError: Identifier 'temp' has already been declared
                    return 1;
                }
            }
        })();
    Copy the code

    看出来了吗?只要是在let声明所在的作用域,就不允许再次声明同名变量(包括函数声明)

    var foo = 1;
        if(true) {
            foo = 2; // Uncaught ReferenceError: foo is not defined
            let foo;
        }

    看到let的’霸道‘了吧?只要在let所在的作用域,同名的变量就会被let占有,不允许重复声明,同时也要遵守let的规则

  4. 全局变量不再作为window对象的属性
    var foo = 1;
        (function() {
            bar = 2;
        })();
        window.foo; // 1
        window.bar; // 2

    是的,es5中,全局变量(包括意外泄露的)都将自动被添加为window对象的属性

    let foo = 1;
        
    window.foo; // undefined

    一切尽在不言中。。。

const

  1. let所拥有的特性,const都有,同时const还有一条:const声明的变量必须进行初始化,并且不能再被重新赋值
    const temp = 1;
        temp = 2; // Uncaught TypeError: Assignment to constant variable.

    注意是不能被重新赋值,这样是比较准确的,其实const声明的变量是可以被修改的,当const声明的变量被初始化为复杂数据类型时,const声明的变量就是可变的,至于为什么,自己理解喽(变量标识符中保存的只是复杂数据类型内存地址而已。。。)

    const temp = {};
        temp.foo = 'aa'; // 这里没问题
        temp = {foo: 'aa'}; // 这里就会抛出异常

     

for循环中的变量声明

前面在记录let块级作用域的时候,我们使用了一个for循环的例子,这里我们不妨试着解析一下for循环的执行过程

Copy the code
var fnArr = [];
    for(var i = 0; i < 3; i++) {
        fnArr.push(function() {
            console.log(i);
        });
    }

    // 伪代码
    var fnArr;
    fnArr = [];
    {
        var i;
        i = 0;

        if(i < 3) {
            fnArr.push(function() {
                console.log(i);
            })
        }
        i++;
        if(i < 3) {
            fnArr.push(function() {
                console.log(i);
            });
        }
        i++;
        ...
    }
Copy the code

这里可惜清晰得看到所有的i都是一个i。。。那使用了let以后呢?

Copy the code
var fnArr = [];
    for(let i = 0; i < 3; i++) {
        fnArr.push(function() {
            console.log(i);
        });
    }

    // 伪代码
    var fnArr;
    fnArr = [];
    {
        let i;
        i = 0;

        if(i < 3) {
            let i = i;
            fnArr.push(function() {
                console.log(i);
            })
        }
        i++;
        if(i < 3) {
            let i = i;
            fnArr.push(function() {
                console.log(i);
            });
        }
        i++;
        ...
    }
Copy the code

Is not see the point of tricks? In fact, we can understand, in each cycle are re-declare i, and i is assigned to the outer layer of the current value. (Note that ah, here is pseudo-code, easy to understand, in practice let i = i will throw exceptions)

Guess you like

Origin www.cnblogs.com/itzlg/p/11300764.html