购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 let声明

对于ES6之前的版本,开发者若想定义变量只能通过关键字var,ES6为开发者提供了关键字let来定义变量。使用关键字let定义变量的方法与使用关键字var定义变量的方法是十分相似的,使用关键字let定义变量同样有三种方式,这里不再对这三种方式做过多演示和讲解,只使用“在声明的同时进行赋值”的方式来定义变量,比如:

从运行结果可以发现,当环境为全局时,使用关键字let定义变量和使用关键字var定义变量的效果是相同的。那ES6为什么要提供关键字let呢?

下面针对关键字let的三个特点依次和关键字var进行对比,如图2-5所示。

图2-5 关键字var与关键字let的对比

如图2-5所示,使用关键字var定义的变量是可以重复声明的,但没有块作用域,并且浏览器在解析时会进行变量声明提升处理;使用关键字let定义的变量是不可以重复声明的,但有块作用域,并且浏览器在解析时不会进行变量声明提升处理。

这里出现了一个新名词“块级作用域”(一般简称为“块作用域”,本书统称为“块作用域”),可能大家会出现疑惑:前面已经学习了函数作用域和全局作用域,怎么又出现一个块作用域呢?其实函数作用域和全局作用域是ES5中的概念,块作用域是ES6中新增的概念。在一个代码块中(括在一对大括号中)定义的所有变量在代码块的外部是不可见的,也就是说,块作用域是以大括号进行界定的,定义在代码块中的变量,在代码块外不能被访问。

2.2.1 let声明的块作用域

let声明与var声明的区别在于二者声明范围的不同。let声明的变量是存在块作用域的,但var声明的变量是没有块作用域的。比如:

在这段代码中可以明显地看到,var声明的变量id是在if语句的大括号内部声明的,而且在if语句的内部或外部都可以访问到该变量,这充分说明var声明的变量可以在块的外部访问。在相同的情况下,当将变量声明的关键字变为let时,只有在内部访问时才能访问到该变量的值,在外部是访问不到的,而且还会报出ReferenceError:id is not defined的错误。这证明let声明的变量只能在当前块作用域(if语句的大括号区域)中访问,外部访问不到该变量。

注意:

在前端开发中,经常会出现ReferenceError:xxx is not defined的错误,ReferenceError是引用错误的意思,代表当一个不存在的变量被引用时发生的错误。简单地说,就是在当前作用域找不到该变量。通常,遇到该错误时的解决方法是先看当前作用域中是否存在该变量,然后梳理逻辑解决即可。

let关键字和var关键字还有一个特性是完全相反的,使用var关键字定义的变量可以多次重复声明,而使用let关键字定义的变量是不能重复声明的,比如:

2.2.2 暂时性死区

在前面的学习中,我们知道var关键字声明的定义会出现声明提升,比如:

这段代码中var定义的变量会被声明提升,因此输出undefined。但是如果将var改为let就不会输出undefined,而是出现报错现象。因为ES6明确规定:如果区块中存在let命令,那么这个区块对这些命令声明的变量从一开始就形成了封闭作用域。如果在声明之前使用这些变量,就会出现报错现象。这在语法上叫作暂时性死区(Temporal Dead Zone,TDZ)。简单地说,let声明的变量不会预处理,因此没有变量声明提升,这与var关键字定义的变量截然相反,比如:

运行这段代码后,控制台会出现ReferenceError的错误。这是因为变量id在声明没有完成前先进行了读取,从而导致报错。 wrPuHQh4xlZF5HWxm5SfHn2+qvQkELXRvrvFFjayxhxSNOTWHjW1vFymLV43XKmu

点击中间区域
呼出菜单
上一章
目录
下一章
×