变量创建分创建,初始化,赋值三个步骤。
故暂时性死区原理:执行函数时才有进行编译,抽象语法树(AST)在进入函数阶段就生成了,并且函数内部作用域是已经明确了,所以进入块级作用域不会有编译过程,只不过通过let或者const声明的变量会在进入块级作用域的时被创建,声明的变量被提升,但变量只是创建被提升,初始化并没有被提升。在该变量没有赋值之前,引用该变量JavaScript引擎会抛出错误—这就是“暂时性死区”。(其实变量已经在内存中了,但是因为语法规定,所以提前访问会会报错)
执行上下文包括 变量环境(含outer)、词法环境和this。函数内部不同声明的变量,在编译阶段会被存放到不同环境里面。Var声明的会放入变量环境中,let和const会放入词法环境中。查找变量时,优先在词法环境中搜索。执行上下文是唯一的,作用域链是不限的。
在ES5规范中,var声明的变量和函数定义会存在变量环境中,ES6规范中,变量环境只存放var声明的变量,函数定义与let,const声明的变量会存在词法环境中。
编译并创建执行上下文的情况有以下三种:
1、当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份。
2、当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
3、当使用 eval 函数的时候,eval 的代码也会被编译,并创建执行上下文。
作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。
词法作用域就是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。函数的作用域链是在声明位置就已经确定好了的。
在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。
块级作用域就是通过词法环境的栈结构来实现的,而变量提升是通过变量环境来实现。