ES6系列——之变量提升(三)

关于ES6的变量提升是一个比较有争议的话题,在大量的资料或者文章上面都会说到ES6不存在变量提升。但是我们从之前说到的暂时性死区这种特殊的模式中去分析,如果不存在变量提升就会出现一些不成立的现象,为此我也查阅了很多的资料和文章。


首先我们来看一下MDN 英文版的原文,发现写的也是:

In ECMAScript 2015, let do not support Variable Hoisting, which means the declarations made using “let”, do not move to the top of the execution block.

在ECMAScript 2015中,不要支持可变提升,这意味着使用“let”进行的声明不会移动到执行块的顶部。

ECMA-262.pdf中是这样写的:

let and const declarations define variables that are scoped to the running execution context”s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable”s LexicalBinding is evaluated.

这说明即使是 block 最后一行的 let 声明,也会影响 block 的第一行。这就是提升(hoisting)(这句话存疑)。

这里我们要重点说明之前说过的一句话 “ES6明确规定,如果在区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域,只要在声明之前就是用这些变量,就会报错。”

下面我们来看一下ES6中的 暂时性死区 最终说明我们的结果:

  1. var a = 123;
  2. if(true){
  3. b = "abc"; //b is not defined
  4. let b;
  5. }

上面的代码在执行到第三行,给声明变量之前调用了变量并赋值的时候出现了报错,那么如果我们在if块级作用域中不声明变量b,那么这个变量将会正常运行,且创建了全局变量b。如下:

  1. var a = 123;
  2. if(true){
  3. b = "abc"
  4. }

上面的代码会正常执行。并且创建全局变量b。以此同时,我们要说到另一个重点,ES6规定在当前作用域中未声明变量之前,不可以调用该变量,否则会报错。


总结:ES6存在变量提升,在块级作用域一开始会去将声明的变量记录下来,但是在未声明变量之前调用了该变量则会报错。

评论: