美文网首页
深入浅出ES6教程『let、const』

深入浅出ES6教程『let、const』

作者: 苏日俪格 | 来源:发表于2018-06-06 14:16 被阅读40次

    ☞☞ 个人主页欢迎访问 ☜☜


    大家好,本人名叫苏日俪格,大家叫我 (格格) 就好,在上一章节中我们了解到一些关于ES6的知识,下面我们一起来继续学习ES6的新特性let和const:

    let和const都是定义(声明)用的,let是声明变量,而const是声明常量的;
    变量:定义完了可以改变
    常量:定义完了无法改变

    var虽然也是声明变量的,不过var声明有很多潜在的问题,至于是哪些问题,让我们来看一个例子:

    for (var i=0; i<10; i++) {
        //coding
    }
    alert(i);  // i=10
    

    小白:⊙⊙这不科学啊,在外面还能访问?
    格格:这个时候有的朋友看了就感觉很神奇,尤其是学Java的,不应该是这样的对吧,但事实如此,接着往下看你就明白了

    如果非得说到作用域的问题的话,那么有两种作用域,一个是全局作用域,另一个就是函数作用域(局部作用域),在这个例子里面声明的i就是一个全局的变量,所以下面是可以访问到的,如果下文继续使用i的话,那么就要从i=10开始,后果不堪设想。

    下面我们再来看一个例子:

    var a = 1;
    function test(){
        alert(a);  // a = undefined
        var a = 2;
    }
    test();
    

    这个例子暴露了一个问题,其实也不算是问题,就是因为JavaScript具有自己的特性:变量提升的问题和预解析的问题,这到底是个什么东西呢?上面的例子可以也看成是下面的例子:

    var a = 1;
    function test(){
        var a;
        alert(a);
        a = 2;
    }
    test();
    

    相信大家已经看懂了,在代码执行的过程中,事先定义了一个a,这时并没有赋值,a当然就是undefined;

    由此我们给出一个定义:变量提升意思就是在js执行之前,会把变量提到顶部,而且不会突破作用域;再看一下预解析的例子:

    <script type="text/javascript">
        var a = 1;
    </script>
    <script type="text/javascript">
        alert(a);  // a = 1
    </script>
    

    JavaScript虽然是一个脚本语言,无需解析,但是它还是有一个小小的预解析的过程:
    读取一个script标签 ==> 预解析 ==> 执行代码 ==> 再读取下一个script标签 ==> ...依次循环

    下面让我们回到let和const:

    for (let i=0; i<10; i++) {
        //coding...
    }
    
    alert(i);   // i is not defined
    

    大家可以看到,同样的例子使用let定义i的话,外面调用就会报错,那么这又是因为什么呢?

    这就是ES6中引入的新特性:块级作用域
    块级作用域就是{ coding... } 只要是带有{}的都是一个块级作用域,下面到了考察大家的时刻了:

    let a = 1;
    function test(){
        alert(a);
        let a = 2;
    }
    test();
    

    和之前的例子一样,只不过将var换成了let,这个时候的结果就是a is not defined,因为let只在块级作用域中起作用,所以a不可能是1,由于let不能提升,所以a就是未定义。
    综上所述:let的第一个特性就是不存在变量提升

    小白:什么鬼?什么叫做第一个特性,难道还有第二个特性不成 ‸?
    格格:那么我要在这里恭喜你中了大奖了,回家准备买彩票吧,它确实有第二个特性<( ̄ˇ ̄)/

    下面在让我们一起看一个例子:

    let a = 1;
    let a = 2;
    alert(a);
    

    这个时候你会发现,它和var是有着非常大的区别的,正常使用var的时候大家都知道,a肯定是等于2的,那么在这里Identifier 'a' has already been declared,这句话的意思是a已经被定义了,也就是说let不允许重复定义同一个变量

    格格:这就是它的第二个特性了,接来下我们要讲的就是let的第三个特性ʅ(´౪)ʃ
    小白:什么?o( ̄ヘ ̄o#) 还有第三个?
    格格:其实第三个即是第二个,第二个即是第三个つ﹏⊂

    下面我们来看一个例子:

    for (let i=0; i<10; i++) {
        let i = 2;
        console.log(i);
    }
    

    小白:so easy!i已经被定义了呗
    格格:嘿嘿,被忽悠了吧,答案是输出了10个2
    小白:(・∀・*) 为啥子嘛

    刚才说到,不允许重复定义一个变量,但它的条件肯定是建立在块级作用域下的呀,这个循环中的i是作用域里面的i的父级,所以在里面还是可以定义的,第三个特性就算是给第二个加个补充:在不同作用域下,可以重复定义

    小白:噢噢,刚才好像被晃了一下子→_→
    格格:ㄟ( ▔, ▔ )ㄏ

    const的特性和let是一模一样的,不同的就只是常量而已,即为定义完了不能修改,否则报错

    下面又到了考察大家的时刻了:

    const arr = ['aaa','bbb','ccc'];
    arr.push('ddd');
    console.log(arr);  // ["aaa", "bbb", "ccc", "ddd"]
    

    小白:说好的不能修改了?你在逗我。。。
    格格:哈哈,你又不懂了吧

    为什么会这样?下面引用大神阮一峰的ECMAScript 6 入门

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

    这个arr是一个数组,即是一个对象,对象本身是存在引用的,如果想让数组无法修改的话,也有办法的,可以用Object.freeze(对象)

    格格:所以呀,var就当做是你的前任,忘了吧...
    小白:哪能说忘就忘,相信自己会慢慢接受现任的

    关于let、const我们都已经了然于心,预知解构赋值如何,请听下回分解 (^∀^)/~~~

    本文的所有内容均是一字一句敲上去的,希望大家阅读完本文可以有所收获,因为能力有限,掌握的知识也是不够全面,欢迎大家提出来一起分享!谢谢O(∩_∩)O~

    欢迎来我的GitHub,喜欢的可以star,项目随意fork,支持转载但要下标注,同时恭候:我的博客 Resume

    等一下( •́ .̫ •̀ ),我还有最后一句话:
    这里虽然没有都市的繁华,
    也没有山林的鸟语花香,
    只有一片如水的宁静,
    古人云:
    既来之则安之,
    既然来到了这里,
    就可以静心休憩你的灵魂,
    调养你疲惫的心,
    再见...

    相关文章

      网友评论

          本文标题:深入浅出ES6教程『let、const』

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