浏览器中的JavaScript执行机制

本文深入探讨了JavaScript中的变量提升、词法作用域、全局作用域、函数作用域和块级作用域,以及作用域链的工作原理。通过一个具体的例子分析了变量查找的过程,解释了在`console.log(test)`时,如何沿着作用域链找到`test`变量的值,揭示了JavaScript引擎在执行代码前的编译阶段如何处理变量和函数声明。
摘要由CSDN通过智能技术生成

我们来分析下面这个例子,当运行到console.log(test)时,输出的结果是什么?

function bar() {
    var myName = "bar"
    let test1 = 100
    if (1) {
        let myName = "bar bar"
        console.log(test)   
    }
}

function foo() {
    var myName = "foo"
    let test = 2

    {
        let test = 3
        let myName = "foo foo"
        bar()
    }
}

var myName = "global"
let test = 1
let myAge = 10
foo()

执行到第6行 console.log(test) 时的调用栈如下:

JS当前调用栈

变量提升

JavaScript 代码执行过程中,需要先做变量提升,之所以需要实现变量提升,是因为 JavaScript 代码在执行之前需要先编译。

在编译阶段,变量和函数会被存放到变量环境中,变量的默认值会被设置为 undefined。在代码执行阶段,JavaScript 引擎会从变量环境中去查找自定义的变量和函数。

如果在编译阶段,存在两个相同的函数,那么最终存放在变量环境中的是最后定义的那个,这是因为后定义的会覆盖掉之前定义的。

var myName = "global"  

这行代码实际是分两步执行,先声明再赋值。

var myName          //声明部分
myName = "global"   //赋值部分

编译阶段 myName 被存放到变量环境中,变量默认值被设为 undefined.
所以没执行到赋值这一步时,myName的值都为 undefined.

词法作用域

词法作用域就是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。

全局作用域、函数作用域和块级作用域

在ES6之前,ES的作用域只有两种:全局作用域和函数作用域,ES6通过词法环境实现块级作用域。通过 let 或者 const 声明的变量,在编译阶段会被存放到词法环境中。

在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。

如上图所示,bar执行上下文的词法环境中,有栈1和栈2两个栈。

let myName = "bar bar" 

被存放到栈1,

let test1 = 100 

被存放到栈2。

作用域链

作用域链是通过词法作用域来确定的.,在每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文,我们把这个外部引用称为 outer。

当一段代码使用了一个变量时,JavaScript 引擎首先会在“当前的执行上下文”中查找该变量。沿着词法环境的栈顶向下查询,如果在词法环境中找到就直接返回给 JavaScript 引擎,如果没有查找到,那么继续在变量环境中查找。如果在当前的变量环境中没有查找到,那么 JavaScript 引擎会继续在 outer 所指向的执行上下文中查找。

分析例子

console.log(test) 在bar的执行上下文中,bar的词法环境中有栈1和栈2两个栈,栈1和栈2都没有找到test变量,接着去bar的变量环境3中查找,3中也没找到test变量,接着通过outer找到全局执行上下文,在全局执行上下文的词法环境中,栈4保存了test变量,所有test变量的实际值是1。

所以,查找test的顺序为:
1 - > 2 -> 3 -> 4
在全局执行上下文中的词法环境中找到test变量,该值为1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值