美文网首页
var、let、const

var、let、const

作者: 几岁老人 | 来源:发表于2016-12-22 16:34 被阅读0次

    1.let:声明变量,有块级作用域,不允许在同一作用域内重复声明,在不同作用域内可以重复声明,let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响(称为暂存死区),循环中的let作用域,注意浏览器兼容性。
    2.var:声明变量和常量,没有块级作用域,var声明存在变量提升
    3.const:声明一个只读的常量。一旦声明,常量的值就不能改变。也可用于声明对象,数组。
    4.ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
    例子:

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    
    function  test(){
       {
            var  a = 1;
        }
        alert(a); a可以访问到alert出1
    }
    
    function test(){
        {
            let  a = 1;
        }
        alert(a); a不能够被访问到alert报错,因为let具有块级作用域,只在let 声明的那个作用域内可以访问
    }
    
    function test(){
        {
            let  a = 1;
            let  a = 2;  这样会报错在同一作用域下不能重复声明
        }
        alert(a); a不能够被访问到alert报错,因为let具有块级作用域,只在let 声明的那个作用域内可以访问
    }
    
    function test(){
        let  a  =  3;
        {
            let  a = 1;
            let  a = 2;  这样会报错在同一作用域下不能重复声明
        }
        alert(a); alert出3
    }
    
    function test(){
        let  a  =  3;  会报错,因为let在同一作用域下不允许重复声明,而var没用块级作用域相当于在这个作用域声明了a
        {
            var  a = 1;  var没有块级作用域相当于在外面声明了一个a
        }
        alert(a);  
    }
    
    function test(){
        var  a  =  3;  不会报错
        {
            let  a = 1;  这个let声明的a是在当前这个块级作用下的a,不受外面作用域下a的冲突影响
        }
        alert(a);  alert出3
    }
    
    function test(){
        let  a  =  3;  不会报错 因为a = 1 声明在全局 而let a = 3声明在function test()作用域下
        {
              a = 1;  没有声明符声明相当于在全局声明了一个a
        }
        alert(a);  alert出3  就近原则  let a = 3 在函数作用域内
    }
    

    ps:以上实例所用let声明的a为常量所以正确应该全部改为使用const声明

    对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const
    命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

    const foo = {};
    foo.prop = 123;
    foo.prop// 123
    foo = {}; // TypeError: "foo" is read-only
    

    上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    

    上面代码中,常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。

    window.a = 1;
    a // 1
    
    a = 2;
    window.a // 2
    

    顶层对象,在浏览器环境指的是window对象,在Node指的是global对象。ES5之中,顶层对象的属性与全局变量是等价的。上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
    ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function
    命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。

    var a = 1;
    // 如果在Node的REPL环境,可以写成global.a
    // 或者采用通用方法,写成this.a
    window.a // 1
    let b = 1;
    window.b // undefined
    

    上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。

    更详细参考阮一峰let和const

    相关文章

      网友评论

          本文标题:var、let、const

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