var,let,const的区别
let,var,const
var
在ES5中,顶层对象的属性和全局变量是等价的,用var
声明的变量既是全局变量,也是顶层变量
注意:顶层对象,在浏览器环境指的是window
对象,在 Node
指的是global
对象
1 |
|
var声明具有变量提升
1 |
|
在编译后会变成
1 |
|
var声明的变量可以重复声明,后声明的会覆盖之前声明的
1 |
|
在函数中声明var变量是局部变量,不会影响到全局var声明
1 |
|
如果没有使用var声明,相当于在全局声明一个变量
1 |
|
let
let没有变量提升,而且不会挂载到window下,未使用let变量声明前,该变量不可用(暂时性死区)
1 |
|
1 |
|
let具有块级作用域
1 |
|
1 |
|
let在相同作用域下不能重复声明
1 |
|
const
const 声明一个常量,一旦声明就不能更改,也不会挂载到window下面
1 |
|
const必须得初始化,初始化之后不能更改
1 |
|
1 |
|
const 值不能更改实际指的是不能修改变量保存的指针地址,但是指针指向的数据是可以修改的
1 |
|
总结
var
具有变量提升,let
,const
仅提升声明,形成暂时性死区const
初始化必须赋值,let
和var
仅提升创建操作let
和const
有块级作用域,var
没有var
可以重新声明,let
和const
不可以,let
可以在不同作用域下重新声明let
和var
可以改变值,const
不行var
会挂载到window
下,let
和const
不会
最终总结
1.变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
let和const不存在变量提升(这个说法起始不太严谨,声明的变量有提升,只是初始化没有提升),即它们所声明的变量一定要在声明后使用,否则报错
2.块级作用域
var不存在块级作用域
let和const存在块级作用域
3.重复声明
var允许重复声明变量
let和const在同一作用域不允许重复声明变量
4.修改声明的变量
var和let可以
const声明一个只读的常量。一旦声明,常量的值就不能改变,但对于对象和数据这种引用类型,内存地址不能修改,可以修改里面的值。
变量提升的原理
事实上,JS也是有编译阶段的,它和传统语言的区别在于,JS不会早早地把编译工作做完,而是一边编译一边执行。简单来说,所有的JS代码片段在执行之前都会被编译,只是这个编译的过程非常短暂(可能就只有几微妙、或者更短的时间),紧接着这段代码就会被执行。
JS 和其他语言一样,都要经历编译和执行阶段。正是在这个短暂的编译阶段里,JS 引擎会搜集所有的变量声明,并且提前让声明生效。至于剩下的语句,则需要等到执行阶段、等到执行到具体的某一句的时候才会生效。这就是变量提升背后的机制。
暂时性死区
1 |
|
错误观点:控制台什么也不输出(理由:全局作用域有一个 me 变量。代码块第一行这个 me,按照作用域规则,引用父级作用域里的 me)
这是因为 ES6 中有明确的规定:如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。假如我们尝试在声明前去使用这类变量,就会报错。(暂时性死区)
产生暂时性死区的原因(ES6标准):
The variables are created when their containing Lexical Environment is instantiated but may not be accessed inany way until the variable ‘ s LexicalBinding is evaluated .(这些变量是在实例化包含它们的 Lexical Environment 时创建的,但在评估变量的 LexicalBinding 之前不能以任何方式访问。
let / const 会先被创建出来,但还未绑定值,所以不能用
在代码块内,使用let命令声明变量之前,该变量都是不可用的
参考文章
https://juejin.cn/post/6991053348396859428