var的缺陷
在说let
和const
前,我们先来看看var
有哪些让人忍不住吐槽的地方。
对于var
声明的变量来说,只存在函数级作用域和全局作用域。
这种宽泛的作用域对于if
、for
的语法不太友好,试想一下以下代码:
你本来是想要获取-1
却不小心获取到了在for
代码块里声明的第二个i
变量。
同时,从上面代码我们也能看到第二个var
的缺点,就是在一个作用域里可以重复声明同一个变量
例如在下方代码里,index
将会被重复声明,而js并不会报错。
var
能重复声明的机制会让你很轻易地破坏原有的变量,在代码很少的时候或许你能谨慎地尽量不重复声明,但是当代码很多的时候,意外地重复声明变量是难以避免的。
此外var
还存在着一种令人困惑的机制:变量提升,即变量可以在声明之前使用,值为undefined
js会先把var a
提升到作用域的顶部,然后到原代码位置时才执行赋值操作a = 1
。
正是由于var
这些反人类的设计,ES6之后出现了新的声明变量的方式let
和const
let
let
是ES6新增语法,用来声明变量,作为var
的替代品
let
作为ES6新声明变量的方式,必定是要修复传统var
的缺陷。
请记住let
和const
的主要特性
- 块级作用域
- 不能重复声明
- 没有变量提升
- 暂时性死区
什么是块级作用域
前面说过var
是函数级作用域和全局作用域,那么什么是块级作用域呢?
我们可以先拆分一下: “块级” + “作用域”
作用域我们都熟悉,那么什么是块呢?
所谓的块,就是代码块,有一对大括号包裹的区域。
块级作用域
let
声明的变量是块级作用域,换句话来说,就是let
声明的变量的作用域在它声明时所在的代码块里
在块(作用域)外无法访问该变量,这与var声明的变量在函数外无法访问函数内声明的变量是一样的。
不能重复声明
在一个作用域里,无法用let
重复声明同一个变量。
这样可以尽量避免变量被覆盖的情况。
不存在变量提升
前面说过var
的变量提升机制,而let
声明的变量则是必须声明后再使用,否则会报错。
暂时性死区
在了解暂时性死区前,先来看这一段有趣的代码
因为var
会进行变量提升,所以其实在提升时第二个tmp
就覆盖了第一个tmp
变量,最终输出都是abc
。
但是我们把var
换成let
试一下
会报错 Uncaught ReferenceError: Cannot access 'tmp' before initialization
因为在if
块里面let
声明的变量tmp,就相当于“绑定”了这个区域,不再受外部的影响。因此tmp
不能在声明前被访问,哪怕是作用域链中有同名变量。这就是暂时性死区
了解之后,我们这样改一下就不会报错了
总结
let
是作为var
的替代方法被设计的,因此它修复了var
许多缺陷,而平时使用let
应当牢记一个原则: 先声明再使用
const
基础用法
const
也是ES6新语法,用作声明一个常量。
同时const
也和let
一样,具有块级作用域、不能重复声明等特性。
因为const声明的是常量,因此应当在声明时就赋值(初始化),不能像let
一样,先声明再赋值。
被const
声明的变量也无法再重新赋值.
本质
const
本质上并不是保证值不变,而是保证变量指向的那个内存地址不变。
js里的变量本质上是指针,指向一块内存地址,对于原始类型来说,变量指向的那块内存保存的就是它的值,因此变量指向的内存地址不变,变量的值也就不会改变;
但是对于引用类型来说(Object),变量指向的内存地址,保存的只是一个指向实际数据的指针,因此const
只能保证变量指向的地址是固定的(即总是指向另一个固定的地址),但是不能保证变量指向的那个指针的指向不变,因此也就不能保证引用类型的值不变。
参考
部分内容参考自
网道—ES6
《JavaScript高级程序设计第四版》
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!