let,var区别的实现原理以及变量环境、词法环境、执行上下文,作用域链查找
谈起var, let都知道作用域和变量提升两个区别,你知道他们的底层原理吗?
摘要:
var: 当前作用域遇到var关键字会在任何语句执行前都已经完成了声明和初始化,这就是会在声明之前输出变量会得到undefined。解析到var这一行会赋值
let: 当前作用域遇到let关键字会在任何语句执行之前先声明不初始化,这就是会在声明之前输出变量会报错Cannot access 'xxx' before initialization(初始化之前不能访问xxx),也称暂时性死区。等到解析到let那一行才会初始化跟赋值
const: 同let
总结: var跟let,const对比只是解耦了声明跟初始化,var在声明的同时初始化了,let,const仅仅是声明并没有初始化
js代码运行过程
编译先创建上下文并传创建变量环境,词法环境,可执行代码,将执行上下文压入执行栈中
执行当前上下文环境可执行代码
- 变量环境: 通过var声明或者function(){}声明的变量存在这里
- 词法环境: 通过let, const, try-catch创建的变量存在这里
- 可执行代码:变量声明提前后剩下的代码
栗子:
var g1 = 1
let g2 = 2
function fun(){
var f1 = 3
let f2 = 4
{
var o1 = 5
let o2 = 6
console.log(g1,g2, f2, o2)
}
console.log(g1, f1, o1)
}
fun()
console.log(g1, g2)
实际执行顺序
//全局执行顺序
var g1,
let g2
function fun()
g1 = 1
g2 = 2
fun()
console.log(g1, g2)
//fun执行顺序
var f1
let f2
var o1
f1 = 3
f2 = 4
{
let o1
o1 = 5
o2 = 6
console.log(g1,g2,f2,o2)
}
console.log(g1,f1,o1)
全局代码入栈
编译并创建上下文,放入调用栈中

全局代码fun入栈
编译并创建func的执行上下文,放入调用栈中

fun执行到block入栈

block查找 g1过程先查找fun的词法环境 => fun的变量环境 => 全局词法环境 => 全局变量环境。 block打印o2此处已经给o2赋值,放到赋值上面打印o2直接报错 Cannot access 'o2' before initialization(初始化之前不能访问o2)
出栈当block可执行代码执行完毕后block会出栈,执行fun的可执行代码知道fun可执行代码执行完毕后fun出栈

浙公网安备 33010602011771号