var:
- 函数内var的变量会成为函数的局部变量。
- 声明提升:js引擎解析时会把所有变量声明都拉到函数作用域顶部。
- 反复多次在同一作用域var声明同一个变量不会报错,后面的值会覆盖前面的值。
- 在全局作用域下声明的变量会成为Windows对象的属性。
- 函数中未声明就被初始化的变量会被提升到全局上下文声明,成为全局变量,在函数终止仍然可以被调用(禁止这样编码,容易内存泄漏)。
let:
- let声明的变量在其所在块作用域内生效。
- let不允许同一块作用域内重复声明同一变量。
- 嵌套声明同一标识符不会报错(父块和子块都有声明),因为同一块中没有重复声明。
- let不会声明提升,作用域内声明前区域称为‘暂时性死区’,调用会报ReferenceError。
- let在全局作用域声明的变量不会成为Windows对象的属性,相应变量会在页面的生命周期内存续。
const:
- 具备let的以上所有属性
- const声明变量时必须同时初始化变量,且修改可能会报错。
- 初始化基本数据类型,数值不能修改。初始化引用数据类型,可更改对象的属性,但不能修改初始化的指针。如果让整个对象都不能修改,可在声明时使用
Object.freeze()包裹对象,这时再修改属性虽然不会报错,但是会静默失败。
const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址保存的只是一个指向实际数据的指针,
const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。
①相较于var声明,let和const声明可提升性能,当块作用域比函数作用域更早的结束执行时,垃圾回收程序会提前回收const和let声明变量所占内存,而var声明的变量所占内存要等函数作用域执行结束才可被回收。 ②且var声明的全局变量由于挂在了Windows对象上,只有页面关闭才能释放所占内存。