var :
- 使用var 声明变量存在变量提升的情况;
- 使用var 能够对一个变量多次声明,后面的声明的变量会覆盖前面的变量声明;
- 在函数中使用var 声明的变量是局部变量,如果在函数内不使用var 声明,该变量是全局的;
let:
- ES6 新增的命令,用来声明变量,用法类似var,但是声明的变量,只在let 命令所在的代码块内有效。
- 使用let 声明变量不存在变量提升的情况,在声明变量之前,该变量都不可用,也就是大家常说的‘暂时性死区’,使用该变量会报错 Reference Error ;
- 只要块级作用域内存在let 命令,这个区域就不再受外部影响,如下面会报错Reference Error;
var a = 123;
if (true) {
a = 456;
let a;
}
console.log('a', a);
let 不允许在相同的作用域中重复声明,如下:
let a = 20;
let a = 40;
注意:是相同作用域,下面的情况是不会报错的
let a = 20;
if(true){
let a = 40;
}
const:
- 声明的是一个只读的常量,一旦声明,常量的值就不能改变,这意味着const 一旦声明变量,就必须立即初始化,不能留到以后赋值;
- 如果声明之前用var或let 声明过变量,再用const 声明同样会报错。
- const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动,对于简单类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量。
- 对于复杂类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const 只能保证这个指针是固定的,并不能确保变量的数据结构不变。如 声明一个对象,对象里面的数据是可以改变的。
- 其他情况,const 和let 保持一致。
现在总结一下var,let,const他们的区别,围绕下面几点展开:
变量提升:
- var 声明的变量存在变量提升(编译阶段,编译器时将var 变量提升到顶部),即变量可以在声明之前调用,值为undefined。
- let和const 不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错。
暂时性死区:
- var 不存在暂时性死区,原因是var存在变量提升。**
- let 和const 存在暂时性死区,只有等到声明变量的那一行代码出现时,才可以获取和使用该变量.
块级作用域:
- var 不存在块级作用域
- let 和const 存在块级作用域
重复声明:
- var 允许重复声明变量
- let 和const 在同一作用域不允许重复声明变量
修改声明的变量:
- let和var 可以修改声明的变量
- const 声明一个只读的常量,一旦声明常量的值就不能改变,如果是一个对象,可以修改对象的属性值。
使用方面:
-
能够用const 尽量使用const,其他情况下大多数使用let,避免使用var
-
基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
引用数据类型的值是保存在内存中的对象,JS不允许直接访问内存中的位置,所以在操作的时候操作的是对象的引用。
底层实现上: let 和 const 的工作方式是通过 ****JavaScript 引擎来实现的。在 JavaScript 引擎中,每一个变量都会被封装在一个称为“变量对象”的容器中,这个对象包含了所有当前上下文中定义的变量与函数。变量对象类似于一个键/值对的容器,其中键是变量名,值是变量的值。在 JavaScript 引擎中,使用 let 和 const 定义变量,实际上是将该变量定义在了一个块级作用域中,而块级作用域是由编译器在编译阶段中实现的。