导读
迄今为止,ES6(ES2015) 发版已经 4 年了,ES6 其中一个特性是加入了新的变量声明方式,鼓励使用const和let关键字声明的块级作用域变量取代var关键字声明的函数作用域变量,这一愿景到现在也普遍得到了实现。但我在功能迭代修改一个同事代码时发现了一个问题,他使用const和let的方式让我感到非常疑惑,我去询问 他得到了他的解释:声明基本数据类型变量时使用let,声明对象类型变量时使用const
随即我找到了关于const、let正确用法的文档,交给了我的同事,也由此有了这篇博客。
为何推出块级作用域取代函数作用域
函数作用域——var
相信大家都遇到过相似问题,如果我们使用”for”循环来向一个数组 push 函数,函数中使用了”for”的循环值”i”,在循环结束后,我们发现执行这个数组中任意的函数,他们中的”i”的值都是一样的
1 | var arr = []; |
这种情况与我们期望的不一样,我们想要得到的值是 “6”,为什么在这里变成了 “10”?
原因是使用var声明的”i”变量提升了,V8 引擎执行前就将变量”i”的声明提升到了这段代码所在的函数体中(若”for”不在函数中则提升到所在 js 文件中),此时的”i”是已被声明,但未被定义具体值
1 | var arr = []; |
所以在”for”执行完成之后,被提升到函数作用域中的”i”在最后一次”i++”后变成了循环边界值”++”也就是 “10”
为了解决这一问题,我们不得不使用可能引起内存泄漏的闭包来达到我们想要的效果
1 | var arr = []; |
由此,应该也感受到了在这个变量提升这一点上 JavaScript 对我们“浓浓的恶意”
块级作用域——const、let
千呼万唤始出来,2015 年 ECMA 终于推出了ES6 推出了新特性块级作用域(关键字const、let),接上面的例子,将var关键字改为let关键字
1 | const arr = []; |
只是将var关键字换为let关键字,就得到了我们想要的结果,也避免了使用闭包导致内存泄漏的风险,是不是很神奇?我们再看一下”i”有没有被提升
1 | const arr = []; |
很棒,”i” 没有被提升
const、let的区别
那么同样是声明块级作用域变量的const和let,它们有什么区别呢?
const:常量,常数
let:允许,让;出租;假设;妨碍
跟字面意思相同,const声明的变量不能够再次被修改 基本类型不能更改值,引用类型不能更改引用,但可以更改属性值
1 | const num = 10; |
let声明的变量可以随意进行赋值
1 | let obj = 10; |
后记
关注生态,可能情况下尝试使用新的东西,我们可能更早的体验到一些好东西 也许是新特性,也许是语法糖(可能甜的齁人)
拜~
