JS|变量提升到块级作用域

变量提升是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提供合理的语义

参考资源:

浏览器工作原理|块级作用域|变量提升

Why is there a “temporal dead zone” in ES6?

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享