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出栈

 

posted @ 2021-03-25 18:54  盐焗小羊腿  阅读(235)  评论(0)    收藏  举报