美文网首页
深入理解ES6(2)

深入理解ES6(2)

作者: Ztry | 来源:发表于2017-11-12 21:12 被阅读0次

    第1章 块级作用域绑定


    1. var声明及变量提升(Hoisting)机制

    • 基于js原生是没有块级作用域的,看下面两段代码的比较就能理解变量提升机制
    function getValue(condition){
        if(condition){
            var value = "blue";
            // ...
            return value;
        }else{
            // 可访问value,其值为undefined
            return null;
        }
        // 可访问value,其值为undefined
    }
    <!-- 以上函数等同于以下的 -->
    function getValue(condition){
        var value;
        if(condition){
            value = "blue";
            return value;
        }else{
            return null;
        }
    }
    //变量提升机制不止在函数中的局部变量,全局变量也有提升
    

    2. 块级声明

    • 块级声明用于声明在指定块的作用域之外无法访问的变量;
    • 块级作用域(词法作用域)存在于函数内部,块中({}之间)

    2.1 let声明

    function getValue(condition){
        if(condition){
            let value = "blue";
            return value;
        }else{
            //此处value不存在
            return null;
        }
        //此处value不存在
    }
    

    2.2 禁止重声明

    var count = 30;
    let count = 40; //TypeError
    if (condition){
        let count = 40; //内嵌不会,可以重声明,作用域不同
    

    2.3 const声明

    //const声明的是常量,使用const要初始化并且不可更改
    const maxItems = 30;
    const name; //SystaxError
    

    2.3.1 const & let

    • const & let 都是块级标志符,块执行完就销毁,不会被提升到作用域顶部
    • 变量不能重复声明
    var message = "Hello!";
    let age = 25;
    //以下报错 TypeError
    const message = "Goodbye";
    const age = 30;
    
    • let 与 const的区别:const不可再赋值,对象可以
    const maxItems = 5;
    maxItems = 6;//TypeError;
    const person = {
        name: "Nicholas"
    };
    //可以修改对象属性值
    person.name = "Greg";
    //不可以修改对象本身
    person = {
        name: "Greg"
    };
    

    2.4 临时死区(Temporal Dead Zone)

    • 变量不会被提升,在声明之前调用这一位置就称为临时死区,会报错
    if(condition){
        console.log(typeof value); //ReferenceError
        let value = "blue";
    }
    //对比
    if(condition){
        console.log(typeof value); //"undefined"
        var value = "blue";
    }
    //对比
    console.log(typeof value); //"undefined"
    if(condition){
        let value = "blue";
    }
    
    • TDZ临时死区是块级绑定的特色,一般是块级作用域中使用let & const,变量不提升

    3. 循环中的块作用域绑定(笔试面试常考)

    • 变量提升和循环
    for(var i = 0;i < 10;i++){
        process(items[i]);
    }
    console.log(i); // 10
    
    for(let i =0;i<10;i++){
        process(items[i]);
    }
    console.log(i); //RerefenceError
    

    3.1 循环中的函数

    var funcs = [];
    for(var i = 0;i<10;i++){
        funcs.push(function(){
            console.log(i);
        });//这个只是把函数放进去数组,并没有调用
    }
    funcs.forEach(function(func){
        func(); //输出10个10
    });
    
    • 以前用立即调用函数表达式(IIFE)解决,强制生成计数器变量副本
    var funcs=[];
    for (var i = 0;i<10;i++){
        funcs.push((function(value){
            return function(){
                console.log(value);
            }
        }(i)));
    }
    funcs.forEach(function(func){
        func();//输出0,1,2,3,4,5,6,7,8,9
    });
    

    3.2 循环中的let声明

    • let声明模仿IIFE,每次迭代循环都会创建一个新变量,并以之前迭代中同名变量的值将其初始化
    var funcs=[];
    for(let i = 0;i<10;i++){
        funcs.push(function(){
            console.log(i);
        });
    }
    funcs.forEach(function(func){
        func();//输出0,1,2,3,4,5,6,7,8,9
    })
    
    var funcs=[];
    obj = {
        a: true,
        b: true,
        c: true
    };
    for(let key in obj){
        funcs.push(function(){
            console.log(key);
        });
    }
    funcs.forEach(function(func){   //func是funcs中的每一项
        func(); //输出a,b,c
    });
    

    3.3 循环中的const声明

    • 如果有重复赋值操作就会报错
    var funcs=[];
    for(const i = 0;i<10;i++){
        console.log(i);//第二次就报错了: TypeError:Assignment to constant variable
    }
    
    • 没有重复赋值就没有问题
    var funcs=[];
    obj = {
        a: true,
        b: true,
        c: true
    };
    for(const key in obj){
        funcs.push(function(){
            console.log(key);
        });
    }
    funcs.forEach(function(func){
        func();//输出a,b,c
    });
    

    4. 全局块作用域绑定

    • let&const 与 var的区别:var 定义全局变量是会把原先的全局对象覆盖掉的,而let&const只是遮蔽作用,看例子就明白了
    var RegExp = "hello!";
    console.log(window.RegExp); //”hello!"
    var ncz = "Hi";
    console.log(window.ncz);    //"Hi"
    
    let RegExp = "Hello!";
    console.log(RegExp);    //"Hello!"
    console.log(window.RegExp === RegExp); //false
    const ncz = "Hi!";
    console.log(ncz);   //"Hi!"
    console.log("ncz" in window); //false
    
    • 有时希望全局对象下定义变量,可以使用var,常见于浏览器跨frame或者跨window访问代码

    5. 块级绑定最佳实践的进化

    • 普通开发中默认使用let而不是var,需要保护的变量则要使用const;
    • ES6开发中,默认使用const,需要变化的使用let

    小结

    1. 块级作用域绑定的let和const为js引入词法作用域,他们声明的变量不会提升,只能在声明的代码块中使用;
    2. 临时死区(TDZ):变量声明前访问块级绑定导致错误的位置
    3. let & const 与 var 在循环中的差异
    4. 块级绑定的最佳实践:默认使用const,需要变化的值用let

    相关文章

      网友评论

          本文标题:深入理解ES6(2)

          本文链接:https://www.haomeiwen.com/subject/iabomxtx.html