var、let、const

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)