0x01 es6 之前的作用域
- 全局作用域
- 函数作用域
由于上面的两种作用域,在 JavaScript 中存在一个术语:变量提升(hoisting),如下:
1 | function func(){ |
执行的结果并不是”test
is not defined” ,而是 undefined
.
这是因为在执行 func() 时,使用 var 定义的 test
被提升到函数顶部进行定义(var test),与下面的代码的结果相同:
1 |
|
0x02 es6 的块级作用域
由于let和const属于ES6,所以都必须使用严格模式,否则会报错
1 |
let
let 与 var 类似,都是用来声明变量的,但是与 var 相比,let 存在以下特点:
1.let 所定义的变量,只在块级作用域内部有效
2.let没有‘变量提升’的特性,而是‘暂时性死区(temporal dead zone)’特性
let 在块级作用域内生效
1 | ; |
可以看到,在 if 外无法访问到 i 的值.
如果用 var 定义,在 if 外层也可以访问到:
暂时性死区
1 | ; |
换成使用 var 定义 i:
在let声明变量前,使用该变量,它是会报错的,而不是像var那样会‘变量提升’。
其实说let没有‘变量提升’的特性,不太对。或者说它提升了,但是ES6规定了在let声明变量前不能使用该变量。
如下:
1 | ; |
如果let声明的变量没有变量提升,应该打印’1’(func函数外的test);而他却报错,说明它是提升了的,只是规定了不能在其声明之前使用而已。我们称这特性叫“暂时性死区(temporal dead zone)”。且这一特性,仅对遵循‘块级作用域’的命令有效(let、const)。
1 |
|
1 |
|
一个经典案例:
1 | var arr = []; |
arr[1]()
会输出2,原因是var声明的变量会变量提升,且当执行arr[1]函数时,i取自于父函数的i,而此时i已经变为2了,所以就会打印2咯。
1 |
|
1 |
|
const
const命令与let命令一样,声明的变量,其作用域都是块级。
所以const遵循的规则与let相差无二,只是,const是用来声明恒定变量的。
且,用const声明恒定变量,声明的同时就必须赋值,否则会报错。
1 |
|
const 正确的使用方式为声明的同时并赋值:
1 |
|