let/const 不存在变量提升,不允许在声明之前使用

  1. console.log(a);
  2. let a = 1;

报错 「Uncaught ReferenceError: Cannot access ‘a’ before initialization」
image.png
这是为什么了?其实最开始浏览器从服务器获取的js都是文本(字符串),声明的文件格式「content-type: application/javascript」。浏览器首先按照这个格式去解析代码,也就是进行「词法解析」生成 AST 语法树。
基于 let、const 等声明的变量,在词法解析阶段就已经明确在此上下文中未来一定会存在这些 let、const 声明的变量,在代码执行时,如果在具体声明的变量之前使用了这些变量,浏览器就会报错「Uncaught ReferenceError: Cannot access ‘a’ before initialization」。所以说 let 、const 类似会有一种变量提升,但是本质上并不是变量提升。

let/const 不允许重复声明

在同一上下文中,无论当前基于何种方式声明过变量,都不允许重复声明。var 是可以重复申明的,词法解析可以审核通过,执行阶段遇到已经申明过的,不会重复申明,但是let不行,在词法解析阶段都过不去,不也存在引擎去执行代码的阶段了。

let 不会污染全局

在全局上下文中,基于 var / function 声明的变量,是给 window(GO) 设置属性,基于 let / const 声明的变量是 VO(G) 中,和 GO 是没有关系的。

  1. var a = 1;
  2. window.a // 1
  3. let a = 1;
  4. window.a //undefined
  5. const a = 1;
  6. window.a //undefined

let/const 会生成块级上下文

  1. for(let i = 0; i < 5; i++) {
  2. setTimeout(() => {
  3. console.log(i);
  4. }, 10);
  5. }
  6. // let的实现原理其实和闭包是一样的
  7. {
  8. // 1、let会先形成一个父块作用域,计数器累加
  9. let i = 0;
  10. {
  11. // 每一次循环形成一个子块级作用域
  12. let i = 0; // i每次递增
  13. setTimeout(() => {
  14. console.log(i);
  15. }, 10);
  16. }
  17. i++;
  18. }

let / const 会形成暂时性死区

所谓暂时性死区就是在定义之前使用 let / const 的变量会报错

let VS const

let、const 都是ES6新增声明的变量的语法,区别是 let 创建的变量是可以更改指针指向,也就是可以重新赋值,但是const申明的变量是不允许改变指针指向的。