区别
- var 有声明声明提升 let 、const没有
- var 没有块级作用域概念,可能会污染到全局变量
而let 、const有块级作用域的概念,for 循环(每循环一次就会重新声明一次)、 if 逻辑判断、while 循环等语句后面的 {} 都是一个块级作用域。
function foo(){
for(var a =0;a<3;a++){
console.log(a);
}
console.log(a); //如果用let申明的话,这里会报错
}
foo()
输出:
0
1
2
3
- 同一作用域下let和const不能声明同名变量,而var可以
- 在当前块作用域中存在a使用let/const声明的情况下,给a赋值10时,只会在当前作用域找变量a
而这时,还未到声明时候,let/const会形成暂时性死区
var a = 100;
if(1){
a = 10;
let a = 1;
}
//Cannot access 'a' before initialization
var a = 100;
function b(){
console.log(a)
let a = 1
}
b()
//报错
-
const 声明后不能再修改,一旦声明必须赋值,
如果声明的是Object类型数据,可以修改其属性,但不能修改其整个的值
比如 const obj = { a:1}
obj.a = 2 //可以
obj = {}或1 都会报错,因为重新改变了obj的引用地址了,这里也涉及到了堆和栈的概念简单说一下, 堆 存的是 块(也就是对象属性) 栈 存的是基础类型数据 以及 指向 堆 的内存地址
为什么let和const不能重复声明?为什么let和const存在暂时性死区?
在ES6规范有一个词叫做Global Enviroment Records(也就是全局环境变量记录),它里面包含两个内容,一个是Object Enviroment Record,另一个是Declarative Enviroment Record。函数声明和使用var声明的变量会添加进入Object Enviroment Record中,而使用let声明和使用const声明的变量会添加入Declarative Enviroment Record中。下面是ECMAscript规范中对var,let,const的一些规则约束
- 使用var声明时,V8引擎只会检查Declarative Enviroment Record中是否有该变量,如果有,就会报错,否则将该变量添加入Object Enviroment Record中。
- 使用let和const声明时,引擎会同时检查Object Enviroment Record和Declarative Enviroment Record,如果有,则报错,否则将将变量添加入Declarative Enviroment Record中。
补充:
何为声明提升