console.log(x); // ReferenceError let x = 10;
暂时性死区
JavaScript中暂时性死区(Temporal Dead Zone)、
let声明的变量x会被提升到当前作用域顶部,但是不会进行初始化。
在初始化赋值前,变量x处在一个暂时性死区中,无法被访问。
第一行代码试图访问x,由于还未初始化就出错了。
当执行流运行到let x语句时,对x进行初始化赋值,死区结束。
这时x才能被安全访问,不会产生引用错误。
所以暂时性死区指的是:
let/const变量在声明位置之前的区域,变量存在但无法被引用,读取会抛错。
而var变量就可以在声明位置之前的区域访问,也就是所谓的变量提升。
js内部代码是怎么被执行的
- 编译器负责编译代码,进行词法分析、语法分析等,生成执行引擎可执行的字节码或中间代码。
- 执行引擎加载编译结果,在运行时解释执行代码,管理运行上下文。
- 作用域定义了变量和函数的访问范围,执行引擎会基于作用域链来查找标识符。
变量的三个阶段
- 声明阶段 - 在作用域中注册变量,这时变量不存在绑定。
- 初始化阶段 - 为变量在作用域中分配内存,创建变量绑定,并将变量自动初始化为 undefined。
- 赋值阶段 - 将一个值赋给已初始化的变量。
在编译阶段,编译器会进行预处理:
- var、let和const声明的变量会在声明阶段提升到当前作用域顶部进行注册
- var变量会在初始化阶段初始化为undefined
- let和const变量不会在这个阶段初始化
在执行阶段,引擎会逐行解释执行代码:
- 对var的访问可以在作用域顶部找到并返回undefined
- 对let和const的访问会抛出错误,因为还未初始化,也就是所谓的ReferenceError
- 当执行到let/const声明语句时:
- 在当前作用域中初始化并赋值变量
- 这时才可以正确访问let和const变量
但是因为暂时性死区的存在看起来没有变量提升,其实说const和let没有变量提升也没什么问题,本质上还是明白,不能在let和const之前访问它们声明的变量。