ECMAScript6-let和const命令

▓▓▓▓▓▓ 大致介绍

  ES6是下一代的JavaScript语言的标准,目标是让JavaScript可以用来编写大型的复杂程序,成为企业级开发语言,要查看浏览器对ES6的支持程度可以用阮一峰大佬写的工具ES-Checker

  安装:(需要安装npm(心累),推荐用cnpm)

    npm install -g es-checker
    es-checker

   效果(有具体的支持情况):

 

▓▓▓▓▓▓ let

  let命令,和var的作用一样,都是用来声明变量,只是let命令只在所在的代码块内有效

  经典的例子:

        var a = [];

        for(var i=0;i<10;i++){
            a[i] = function(){
                console.log(i);
            }
        }

        a[4](); //10
        console.log(i); //10

  经典的例子,就不赘述,这里a数组都是引用的同一个i

 

  改用 let:

        var a = [];

        for(let i=0;i<10;i++){
            a[i] = function(){
                console.log(i);
            }
        }

        a[4](); //4
        console.log(i); // ReferenceError: i is not defined

  这里i用let声明,就只在本次循环中存在,每次循环都会创建一个i

 

  注意:在for循环中,循环语句是一个作用域,而循环体内部又是一个子作用域
  例如:

            for(let i=0;i<3;i++){
                let i = 'abd';
                console.log(i);
            }
            
            //abd
            //abd
            //abd

  可以看出循环体内的i和循环语句中的i是分离的

 

▓▓▓▓▓▓ let的特点

  1、不存在变量提升

        console.log(a); //undefined
        var a = '123';

        console.log(b);
        let b = '123'; //ReferenceError: b is not defined

  

  

  2、暂时性死区
  如果在一个块级作用域内有let命令,那他声明的变量就绑定这个块级作用域,不受外部的影响

        var a = '123';

        if(true){
            a = '456';
            console.log(a); //ReferenceError: a is not defined
            
            let a;
            console.log(a); //undefined
        }

 

  

  ES6明确规定,如果区块中存在let或者const命令,这个区块对这些命令声明的变量,从一开始就形成封闭作用域,凡是在声明之前使用这些变量都会报错

  这里a是用let声明的,所以在let声明之前使用a都会报错

 

  3、不能重复声明

  let不允许在同一个作用域内,声明同一个变量

        //报错
        {
            var a = '123';
            let a = '456';
        }

        //报错
        {
            let a = '123';
            var a = '456';
        }

        //报错
        {
            let a = '123';
            let a = '123';
        }

 

 

  注意:在函数内不能重复声明参数

                //报错
                function test(target) {
                    let target;
                }

                //不报错
                function test(target){
                    {
                        let target;
                    }
                }

   在第二个函数里不报错,是应为{}中时一个新的子作用域,和参数target不是在同一个块内了

 

▓▓▓▓▓▓ 块级作用域

  let为JavaScript新增了块级作用域

  使用var是没有块作用域概念的

        var a = '123';

        if(true){
            var a = '456';
        }

        console.log(a); //456

  

  使用let就有了块作用域

        let a = '123';

        if(true){
            let a = '456';
        }
        
        console.log(a); //123

  外层的代码块不受内层代码块的影响

 

▓▓▓▓▓▓ 块级作用域和函数声明

  ES5规定函数只能在顶层作用域和函数作用域中声明,不能在块作用域中声明
  ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
  例如:

            function f(){
                console.log('out');
            }

            (function(){

                if(false){
                    function f(){
                        console.log('in')
                    };
                };

                f();

            }());

 

  在ES5中结果是 'in'。就是函数声明提升,不在多赘述
  在ES6中,理想的结果是'out',但是在浏览器中运行时,却会报错,这是为什么?因为如果这么突兀,那么老的代码就会出现很多的问题,所以,ES6规定浏览器可以有自己的的行为方式
    1、允许在块级作用域内声明函数。
    2、函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
    3、同时,函数声明还会提升到所在的块级作用域的头部。

  注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

  在ES6中实际执行的代码是

        function f(){
            console.log('out');
        }

        (function(){

            var f = undefined;

            if(false){
                function f(){
                    console.log('in')
                };
            };

            f();

        }());

 

  注意:ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

            // 不报错
            'use strict';
            if (true) {
              function f() {}
            }

            // 报错
            'use strict';
            if (true)
              function f() {}

 

 

▓▓▓▓▓▓ const命令

  const声明一个只读的常量,一旦声明,常量的值就不能改变。所以在使用const时,一旦声明就要立即初始化
  const和let一样,只存在与本块作用域中没有声明提升存在暂时性死区不可重复声明

  const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

  例如:

        const a = {
            id: 1,
            name:'qqqq'
        };
        a.id = 2;

        a = {}; //报错

 

 

  参考资料: 

        ECMAScript 6入门-阮一峰

posted @ 2017-03-27 15:59  老板丶鱼丸粗面  阅读(442)  评论(0编辑  收藏  举报