参考es6.ruanyifeng.com
在ES6中新增的let与const两种定义变量的方式,其用法与var相似但是有许多区别如下:
{
var a = "a";
let b = "b";
let c = "c";
}
console.log(a);
//打印 a
console.log(b);
//报错
console.log(c);
//报错
因为let与const有块级作用域所以在打印b与c的时候报错,报错的具体内容是变量未定义。但是var定义的变量没有报错,因为在var定义的变量没有块级作用域的概念。所以a照常打印出来。
同样如下所示:
let temp = 1;
if(temp === 1) {
var a = "a";
let b = "b";
const c = "c";
}
console.log(a);
//打印a
console.log(b);
//报错
console.log(c);
//报错
同样应为const与let有块级作用域的概念,打印b与c报错而a正常打印。这里谈到块级作用域,我们来讲讲什么叫做块级作用域吧。所谓块级作用域我们可会理解为{}包裹的比如for循环中{}包裹的等等都可看为块级作用域。因而我们可以通过块级作用域解决下面几个问题比如:
for(var i=0; i<5; i++) { setTimeout(()=>{ console.log(i) })}
//打印结果
5
5
5
5
5
我们都只到这里打印5行5,原因是setTimeout是异步操作会先执行for循环将i加到5最后打印setTimeout里面的,因为在setTimeout执行前i变成5了,所以打印5次5。详细原因请阅读js的事件循环机制。解决方案之一如下:
for(let i=0; i<5; i++) { setTimeout(()=>{ console.log(i) })}
//打印结果
0
1
2
3
4
这是因为let是块级作用域每循环一次生成一个块级作用域,所以打印结果为0,1,2,3,4
关于变量提升的情况
我们或多或少的都活碰到变量提示的问题这种问题只会发生在var定义的变量下而let与const虽然会出现变量提升的概念但是由于存在暂时性死区,所以给人的表象是不存在变量提升。
举个例子
console.log(foo);var foo = 1;
//打印结果undefined
console.log(foo);let foo = 2;
//报错 Cannot access 'foo' before initialization
关于const不可变性与let不可重复声明
function func() { var a = 1; let a = 1;}func();
//报错
function func() { const a = 1; let a = 1;}func();
//报错
function func() { let a = 1; let a = 1;}func();
//报错
function func() { var a = 1; var a = 1;}func();//正常
var可以重复声明单数let、const不可以重复声明同时const有不可变性例如。
const a = 1;a = 2;
//报错
因为const一旦声明就不能更改了,所以产生报错。但是下面这种情况是对的
const a = [];a.push(1);//正常执行
因为a为引用类型我们只需要保证a的地址不发生改变就行。但是如果执行a=1这个是将引用地址发生改变了,所以报错。
var变量
var a = 1;
b = 10
这两种声明方式看着差不多但是这两个还是不一样,b=10是将b挂载到window对象上面了,如果用delete b是能删掉的,但是a 删不掉,另外将这两个声明方式写到函数中b=10在函数外可以访问到值因为它是挂载到window对象上了,而var a = 1则在函数外不能拿到值因为它变成了函数作用域里面的。
这边文章参考了阮一峰老师的ES6 es6.ruanyifeng.com