es6之 作用域下的 Let 与 const

230 阅读2分钟

1、作用域

概念:变量所作用的范围

查看官方文档

  • es6之前有 全局作用域,函数作用域
  • es6新增 块级作用域, 由 { } 包括,if,for的{} 也属于块级作用域

为了避免块级作用域内声明的函数的处理规则对老代码产生很大的影响,减轻不兼容问题,ES6允许游览器有自己的行为方式,规则如下:

  • 允许在块级作用域内声明函数
  • 函数声明类似 var ,即会提升到全局作用域或函数作用域的头部
  • 函数声明还会提升到所在的块级作用域的头部

2、变量 var

  • var 有变量提升,有初始化提升,值可变
证明 var 存在变量提升
function fn(){
    console.log(a) //undefined
    var a = 1
}
fn()

输出时不应该是报错吗?为什么会输出undefined
原来 js 在创建执行上下文的时候,会检查代码,找出变量声明和函数声明,并将函数声明完全储存在环境中,而将通过 var 声明的变量设定为 undefined,这就是 变量提升
简而言之,变量的提升就是:变量和函数的声明会被移动到函数或者全局代码的开头的位置。

3、块级变量 Let

  • let 有变量提升,没有初始化提升,值可变

块级变量 Let

将证明 var 有变量提升 的 改成 let
function fn(){
    console.log(a) // Uncaught ReferenceError: a is not defined
    let a = 12
}
fn()

结果报错,很多人以这个为例,证明 let 不能变量提升,但是这个只能证明 var 存在变量提升,不能证明 let 不能变量提升。

证明 let 存在变量提升
var x = 'parent value';
(function() {
  console.log(x); // parent value
}())

如果我们在 代码中 加入 let

var x = 'parent value';
(function() {
  console.log(x); // Uncaught ReferenceError: x is not defined
  let x = 'child value'
}())

上面代码输出 parent value ,加入 let 之后报错,那就是涉及到 变量提升 。在变量赋值之前是不能进行读写,否则报错。这就是 let 和 const 的 暂时性死区

image.png

暂时性死区

在相应花括号形成的作用域中存在一个“死区”,从代码块(block)起始到变量求值(包括赋值)以前的这块区域。这个“死区”,专业名称为TDZ(Temporal Dead Zone)。

4、块级常量 Const

  • const 有变量提升,没有初始化提升,值不可变,但如果是定义对象,则属性可变

块级常量 Const

暂时性死区问题说明:其实let和const是有变量提升的,但是没有初始化提升:

块级作用域解决问题:

for(var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  })
} // 5 5 5 5 5


for(let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  })
} // 0 1 2 3 4

参考
因为说let没有变量提升,我被嘲笑了 - 掘金 (juejin.cn)
基础很好?总结了38个ES6-ES12的开发技巧,倒要看看你能拿几分?🐶 - 掘金 (juejin.cn)