>[danger]问题一:什么是提升?什么是暂时性死区?var、let 及 const 区别? 对于这个问题,我们应该先来了解提升(hoisting)这个概念。 ~~~ console.log(a) // undefined var a = 1 ~~~ 从上述代码中我们可以发现,虽然变量还没有被声明,但是我们却可以使用这个未被声明的变量,这种情况就叫做提升,并且提升的是声明。 对于这种情况,我们可以把代码这样来看 ~~~ var a console.log(a) // undefined a = 1 ~~~ 接下来我们再来看一个例子 ~~~ var a = 10 var a console.log(a) ~~~ 对于这个例子,如果你认为打印的值为`undefined`那么就错了,答案应该是`10`,对于这种情况,我们这样来看代码 ~~~ var a var a a = 10 console.log(a) ~~~ 到这里为止,我们已经了解了`var`声明的变量会发生提升的情况,其实不仅变量会提升函数也会被提升。 ~~~ console.log(a) // ƒ a() {} function a() {} var a = 1 ~~~ 对于上述代码,打印结果会是`ƒ a() {}`,即使变量声明在函数之后,这也说明了函数会被提升,并且优先于变量提升。 说完了这些,想必大家也知道`var`存在的问题了,使用`var`声明的变量会被提升到作用域的顶部。 >接下来我们再来看`let`和`const`。 我们先来看一个例子: ~~~ var a = 1 let b = 1 const c = 1 console.log(window.b) // undefined console.log(window. c) // undefined function test(){ console.log(a) let a } test() ~~~ 首先在全局作用域下使用`let`和`const`声明变量,变量并不会被挂载到`window`上,这一点就和`var`声明有了区别。 再者当我们在声明`a`之前如果使用了`a`,就会出现报错的情况 ![](https://user-gold-cdn.xitu.io/2018/11/18/1672730318cfa540?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) 你可能会认为这里也出现了提升的情况,但是因为某些原因导致不能访问。 --- 首先报错的原因是因为存在暂时性死区,我们不能在声明前就使用变量,这也是`let`和`const`优于`var`的一点。然后这里你认为的提升和`var`的提升是有区别的,虽然变量在编译的环节中被告知在这块作用域中可以访问,但是访问是受限制的。 --- 那么到这里,想必大家也都明白`var`、`let`及`const`区别了,不知道你是否会有这么一个疑问, >[info] 为什么要存在提升这个事情呢,其实提升存在的根本原因就是为了解决函数间互相调用的情况 ~~~ function test1() { test2() } function test2() { test1() } test1() ~~~ 假如不存在提升这个情况,那么就实现不了上述的代码,因为不可能存在`test1`在`test2`前面然后`test2`又在`test1`前面。 那么最后我们总结下本题的内容: * 函数提升优先于变量提升,函数提升会把整个函数挪到作用域顶部,变量提升只会把声明挪到作用域顶部 * `var`存在提升,我们能在声明之前使用。`let`、`const`因为暂时性死区的原因,不能在声明前使用 * `var`在全局作用域下声明变量会导致变量挂载在`window`上,其他两者不会 * `let`和`const`作用基本一致,但是后者声明的变量不能再次赋值。