es6语法中的let/const
let/const(常用)
let,const用于声明变量,用来替代老语法的var关键字,与var不同的是,let/const会创建一个块级作用域(通俗讲就是一个花括号内是一个新的作用域)
这里外部的console.log(x)拿不到前面2个块级作用域声明的let:
在日常开发中多存在于使用if/for关键字结合let/const创建的块级作用域,值得注意的是使用let/const关键字声明变量的for循环和var声明的有些不同
for循环分为3部分,第一部分包含一个变量声明,第二部分包含一个循环的退出条件,第三部分包含每次循环最后要执行的表达式,也就是说第一部分在这个for循环中只会执行一次var i = 0,而后面的两个部分在每次循环的时候都会执行一遍
而使用使用let/const关键字声明变量的for循环,除了会创建块级作用域,let/const还会将它绑定到每个循环中,确保对上个循环结束时候的值进行重新赋值
什么意思呢?简而言之就是每次循环都会声明一次(对比var声明的for循环只会声明一次),可以这么理解let/const中的for循环
给每次循环创建一个块级作用域:
暂时性死区
使用let/const声明的变量,从一开始就形成了封闭作用域,在声明变量之前是无法使用这个变量的,这个特点也是为了弥补var的缺陷(var声明的变量有变量提升)
剖析暂时性死区的原理,其实let/const同样也有提升的作用,但是和var的区别在于
-
var在创建时就被初始化,并且赋值为undefined
-
let/const在进入块级作用域后,会因为提升的原因先创建,但不会被初始化,直到声明语句执行的时候才被初始化,初始化的时候如果使用let声明的变量没有赋值,则会默认赋值为undefined,而const必须在初始化的时候赋值。而创建到初始化之间的代码片段就形成了暂时性死区
引用一篇博客对于ES6标准翻译出来的一段话
由let/const声明的变量,当它们包含的词法环境(Lexical Environment)被实例化时会被创建,但只有在变量的词法绑定(LexicalBinding)已经被求值运算后,才能够被访问
回到例子,这里因为使用了let声明了变量name,在代码执行到if语句的时候会先进入预编译阶段,依次创建块级作用域,词法环境,name变量(没有初始化),随后进入代码执行阶段,只有在运行到let name语句的时候变量才被初始化并且默认赋值为undefined,但是因为暂时性死区导致在运行到声明语句之前使用到了name变量,所以报错了
上面这个例子,因为使用var声明变量,会有变量提升,同样也是发生在预编译阶段,var会提升到当前函数作用域的顶部并且默认赋值为undefined,如果这几行代码是在全局作用域下,则name变量会直接提升到全局作用域,随后进入执行阶段执行代码,name被赋值为"abc",并且可以成功打印出字符串abc
相当于这样
暂时性死区其实是为了防止ES5以前在变量声明前就使用这个变量,这是因为var的变量提升的特性导致一些不熟悉var原理的开发者习以为常的以为变量可以先使用在声明,从而埋下一些隐患
关于JS预编译和JS的3种作用域(全局,函数,块级)这里也不赘述了,否则又能写出几千字的博客,有兴趣的朋友自行了解一下,同样也有助于了解JavaScript这门语言
const
使用const关键字声明一个常量,常量的意思是不会改变的变量,const和let的一些区别是
- const声明变量的时候必须赋值,否则会报错,同样使用const声明的变量被修改了也会报错
- const声明变量不能改变,如果声明的是一个引用类型,则不能改变它的内存地址(这里牵扯到JS引用类型的特点,有兴趣可以看我另一篇博客对象深拷贝和浅拷贝)
有些人会有疑问,为什么日常开发中没有显式的声明块级作用域,let/const声明的变量却没有变为全局变量
这个其实也是let/const的特点,ES6规定它们不属于顶层全局变量的属性,这里用chrome调试一下
可以看到使用let声明的变量x是在一个叫script作用域下的,而var声明的变量因为变量提升所以提升到了全局变量window对象中,这使我们能放心的使用新语法,不用担心污染全局的window对象
建议
在日常开发中,我的建议是全面拥抱let/const,一般的变量声明使用let关键字,而当声明一些配置项(类似接口地址,npm依赖包,分页器默认页数等一些一旦声明后就不会改变的变量)的时候可以使用const,来显式的告诉项目其他开发者,这个变量是不能改变的(const声明的常量建议使用全大写字母标识,单词间用下划线),同时也建议了解var关键字的缺陷(变量提升,污染全局变量等),这样才能更好的使用新语法
作者:yeyan1996
链接:https://juejin.cn/post/6844903775329583112
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。