前言
在JS中,var早已深入人心,因此本文将不再赘述,仅在必要时拉出来溜溜。
| 声明方式 | 变量提升 | 暂时性死区 | 重复声明 | 可修改值 | 块级作用域 | 全局变量属于顶层对象 |
|---|---|---|---|---|---|---|
| var | 是 | 否 | 是 | 是 | 否 | 是 |
| let | 否 | 是 | 否 | 是 | 是 | 否 |
| const | 否 | 是 | 否 | 否(引用类型仅保证地址不被修改) | 是 | 否 |
变量提升
a // a is not defined
let a = 'a'
b // b is not defined
const b = 'b'
c // undefined
var c = 'c'
暂时性死区
在代码块内,使用let、const命令声明变量之前,该变量都是不可用的。
其本质是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
typeof a // a is not defined
let a = 'a'
typeof b // b is not defined
const b = 'b'
typeof c // "undefined"
var c = 'c'
以下为几个比较隐蔽的死区:
-
赋值
var a = a let b = b // b is not defined -
函数参数
function foo(a = b, b = 2) { console.log([a, b]) } foo()
重复声明
let a = 'a1'
let a = 'a2' // Identifier 'a' has already been declared
a // a1
const b = 'b1'
const b = 'b2' // Identifier 'b' has already been declared
b // b2
var c = 'c1'
var c = 'c2'
c // c2
修改值
let a = 'a1'
a = 'a2'
a // a2
const b = 'b1'
b = 'b2' // Assignment to constant variable
b // b1
var c = 'c1'
c = 'c2'
c // c2
const 引用类型仅保证引用地址不可修改
const a = {
a1: 1,
a2: 2
}
a.a3 = 3
a // {a1: 1, a2: 2, a3: 3}
块级作用域
{
let a = 'a'
const b = 'b'
var c = 'c'
}
a // a is not defined
b // b is not defined
c // c
全局变量不再属于顶层对象
顶层对象:浏览器中指window,Node中指global。
let a = 'a'
window.a // undefined
const b = 'b'
window.b // undefined
var c = 'c'
window.c // "c"
再也不用担心手抖修改了顶层对象~
解决的问题
-
内层变量覆盖外层变量;

-
用来计数的循环变量变为全局变量;

- 上面代码中,变量j是let声明的,当前的j只在本轮循环有效,所以每一次循环的j其实都是一个新的变量,那么如果每一轮循环的变量j都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量j时,就在上一轮循环的基础上进行计算。
- for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

-
闭包与垃圾回收;
有块级作用域

无块级作用域

-
不再需要使用
立即执行函数,减少代码冗余提升可读性; -
允许在块级作用域中声明函数,函数声明语句的行为类似于
let;原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
1.允许在块级作用域内声明函数。
2.函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
3.同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
参考
-
你不知道的JavaScript(上)
小结
本文主要介绍了let、const与var定义变量的区别以及优点。推荐我用了两个月的时间才理解 let这篇文章,供大家思考。
之前声明变量只能使用var、function,现在ES6添加了let、const、import、class4种方式(import、class 后续也会一一总结),所以现在总共有6种声明变量的方式。SO声明变量,请合理选择。
感谢阅读,如有问题,欢迎指正。
最最最最最后,在这四天的五一小长假里,为大家献上美景 —— 摩洛哥蓝色小镇🇲🇦祝大家五一愉快呦~
