最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ES6中的let和const

    正文概述 掘金(前端好多哦)   2021-03-25   592

    简介

    好像又很久没有写文章了,说实话,写文章这种东西是真的看心情,有时候想写,有时候又不想写,就和过山车差不多哈哈哈,今天我们也不讲深奥的,就讲讲我们在变量声明时很常见的 let 和 const。

    既然讲到 let 和 const,我们就得摸着自己的良心问一下自己,这是什么,为啥出现,它为我们解决了什么样的问题。再此之前,让我们看看在 ES6 之前 var 到底遗留了什么问题给我们。

    var 迷惑操作锦集

    同一作用域可重复声明变量

    var a = 1;
    var a = 2;
    console.log(a);//2
    
    //可以理解成这样
    var a;
    a = 1;
    a = 2;
    console.log(a);
    

    对于这段代码,有人想发表什么意见不。没有啊,我觉得没什么问题啊,很好啊。emmmmm,好像是没什么问题哦,但是当我们需要外部加载多个js脚本的时候,才会突然发现,咦,我这个变量的值怎么和我心里想的不一样,然后开始找bug,抓头发,花了1分钟,一个小时,或者是一天,才知道原来是其他的js脚本也声明了这个变量,把我的变量值给偷偷的改掉了。这还是在js脚本是自己写的情况下,要是其他人写的呢,不得把我坑死。这时候我们才会开始吐槽,为啥声明相同变量浏览器不给我报错啊!心疼自己头发几分钟。

    变量提升带来的问题

    奇怪的数据访问方式

    if(Math.random() < 0.5){
        var a = 1;
        console.log(a);
    }else{
        var a = 2;
        console.log(a);
    }
    console.log(a);
    
    //可以理解成这样
    var a;
    if(Math.random() < 0.5){
        a = 1;
        console.log(a);
    }else{
        a = 2;
        console.log(a);
    }
    console.log(a);
    
    //另一个例子
    console.log(b);//undefined
    var b = 1;
    
    //也可以理解成这样
    var b;
    console.log(b);
    b = 1;
    

    眼尖的小伙伴会说,为啥外面的 console 能读取到变量 a哦,我明明没有在外面声明变量 a,我还蛮期待它会报错的呢。???还有就是为啥能在 b变量声明前就能读到 b啊,这不合常理。

    闭包问题

    for(var i = 1; i <= 10; i++ ){
        var btn = document.createElement("button");
        btn.innerText = "按钮" + i;
        btn.onclick = function(){
            console.log(i);
        }
        document.body.appendChild(btn);
    }
    
    console.log(i);//11
    
    //也可以这样理解
    var i;
    var btn;
    for(i = 1; i <= 10; i++ ){
        btn = document.createElement("button");
        btn.innerText = "按钮" + i;
        btn.onclick = function(){
            console.log(i);
        }
        document.body.appendChild(btn);
    }
    

    这段代码就需要你们在自己的编辑器上运行了,你会发现问题的,嘿嘿。

    污染全局对象成员

    var a = 1;
    console.log(window.a, window.a === a);//1 true
    
    var console = 1;
    console.log(console);//console.log is not a function
    

    直接报错了,还有这种操作,妙啊妙啊。

    上面奇奇怪怪的问题大家应该都知道原因吧,不是吧不是吧,都2021年了,不会有人还不知道把。没有贬义的意思,单纯调侃一下。实在不知道的,可以自己百度搜索一下,随便锻炼你们的动手能力(当然有一部分自己懒的原因,我反思一下),而且今天的重点是 let 和 const。

    没错,他们的出现解决了以上几个问题。

    let

    这是取自于 MDN(Mozilla Developer Network) 中对 let 的一段描述。是不是有点看不懂,其实说白了就是 let 关键字可以将变量绑定到所在的任意作用域中(通常是 { .. } 内部)。换句话说,let 为其声明的变量隐式的绑定了所在的块作用域。怎么理解呢,用之前的代码来解释把。

    if(Math.random() < 0.5){
        let a = 1;
        console.log(a);
    }else{
        let a = 2;
        console.log(a);
    }
    console.log(a);//a is not defined
    

    这个时候你会发现外面的 console 已经读取不到变量 a了,为啥呢,因为变量 a被困在在这个{ .. }里面了,俗称块级作用域,它不会再提升到外面的全局作用域中。

    总结:let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。

    用这个知识再来讲讲上面的闭包问题

    //在没有let之前,可以用立即执行函数来解决
    for(var i = 1; i <= 10; i++ ){
        var btn = document.createElement("button");
        btn.innerText = "按钮" + i;
        (function(i){
            btn.onclick = function(){
                console.log(i);
            }
        })(i);
        document.body.appendChild(btn);
    }
    
    //用let解决更方便
    for(let i = 1; i <= 10; i++ ){
        let btn = document.createElement("button");
        btn.innerText = "按钮" + i;
        btn.onclick = function(){
            console.log(i);
        }
        document.body.appendChild(btn);
    }
    
    console.log(i);//i is not defined
    

    不知道看到这里,你们有没有动手实践过上面的例子,现在我不装了,我摊牌了。之前的结果是不过你点哪个按钮,打出的结果都是11,为啥呢,为啥呢?现在就容许我,这个前端新手给你们解释一下。

    因为当我们点击按钮触发点击事件的时候,里面的循环早已经执行完了,由于 var声明的变量提升问题,执行点击函数的时候,读取到的变量 i其实就是全局环境下的变量 i,而这时候的 变量 i 一直都是11,所以无论你点哪个按钮,打印出来的都是11。那为啥 let声明的变量就可以解决这个问题呢?那是因为每进入一次新的循环体,let 声明的变量 i都会隐式的绑定该循环体中的作用域,这样不同的按钮就都会有各自独自的块级作用域,就很好的解决了上面奇奇怪怪的问题。

    至于 let不允许在同一作用域下声明相同变量,不会污染全局对象成员,这个相对来说就比较简单,就真的靠你们自己自觉动手了啊。

    不过还有一个比较有意思的例子如下:

    function do_something() {
      console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
      let foo = 2;
    }
    
    do_something();
    

    通过上面的讲解,我们得知,let声明的变量不会提升,所以报错的话那也很正常,不过这个报错的信息怎么和我们想的不一样,不应该是foo is not defined嘛,但这里的报错却是Cannot access 'foo' before initialization,意思就是不能在初始化前访问 foo变量。其实这里又会有一个新的知识点,那就是暂时性死区,实际上foo变量声明还是提升了,只不过被放入了暂时性死区,当访问暂时性死区里面的变量,就会报上面的错误,而只有声明了该变量,才能从暂时性死区里面拿出来,进行正常访问。在MDN中是这么说的:

    const

    const 和 let基本有一样的效果,唯一的区别只是 const声明的变量必须在初始化阶段就进行赋值操作,并且不能被重复赋值。这意味了 const一般用来声明一个常量。

    const a;//SyntaxError: Missing initializer in const declaration
    
    const b = 1;
    b = 2;//TypeError: Assignment to constant variable.
    

    但是这里要注意一下,这里说的不能改变指的是声明的变量所持有的值是不可变的,如果持有的值是一个引用对象地址,那么该引用对象内部的内容还是可以改变的。如下:

    const obj = {
        name: "xxx",
        age: 18,
    }
    
    obj.name = "aaa",
    console.log(obj);//{name: "aaa", age: 18}
    

    结语

    今天到这里就讲完了,没想到我们平时这么常见的声明语句也有这么多学问在里面,那么今天就到这里啦,谢谢各位品读,下次光临。


    起源地下载网 » ES6中的let和const

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元