变量提升是ES6之前的缺陷,为了修复这个问题在ES6中加入了块级作用域以及let、const关键字
那么首先为什么会产生变量提升这个缺陷呢,是因为在ES6之前,JS的作用域只有全局作用域和函数作用域:
- 全局作用域中的对象在代码中的任何地方都可以访问,其生命周期也是伴随着页面的生命周期
- 函数作用域则是在函数内部定义的变量或者函数,只能在函数内部被访问,函数执行结束之后就会被销毁
是没有块级作用域这个概念的,因为就没有去设计,当初的设计就是两个作用域,然后把作用域内部的变量统一提升,最初的设计就是这样的,慢慢的发现这样并不是很友好,会产生不符合预期的问题:
- 变量容易在不被察觉的情况下被覆盖掉
- 本应该被销毁额变量没有被销毁
所以在ES6中进行了修复:加入了块级作用域以及let、const关键字
这样在我们的编程中
function foo(){
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
}
console.log(b)
console.log(c)
console.log(d)
}
foo()
// 1 3 2 4 Error
复制代码
let
声明的变量就很符合预期,而var
声明的就很反人类,产生这样的结果的原因是:
- 函数内部通过
var
声明的变量,在编译阶段会存放在执行上下文的变量环境中 - 通过
let
声明的变量,在编译阶段存放在执行上下文的词法环境中 - 函数中的块级作用域的
let
声明的变量存放在词法环境的一个单独的区域中
所以为了更好的编码体验,尽可能的放弃var
,如果你想使用let
来测试var
的变量提升:
{
console.log(name)
let name = '77'
}
// ReferenceError: Cannot access 'a' before initialization
复制代码
这是不允许的,因为ES6中不允许这样写,如果你这样做了。就会抛出一个错误:TDZ—Temporal Dead Zone
为什么会有TDZ:
- 捕捉编程错误
- 为const,let提供合理的语义
参考资源:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END