JS词法环境和执行上下文

本文深入探讨了JavaScript的执行上下文和词法环境,解释了它们在程序执行过程中的作用,包括全局执行上下文、函数执行上下文、执行栈的工作原理,以及let/const与var的区别。理解这些概念对于掌握JavaScript变量提升、闭包等特性至关重要。
摘要由CSDN通过智能技术生成

前言

JavaScript是一门解释性动态语言,但同时它也是一门充满神秘感的语言。如果要成为一名优秀的JS开发者,那么对JavaScript程序的内部执行原理要有所了解。

本文以最新的ECMA规范中的第八章节为基础,理清JavaScript的词法环境和执行上下文的相关内容。这是理解JavaScript其他概念(let/const暂时性死区、变量提升、闭包等)的基础。

本文参考的是最新发布的第十代ECMA-262标准,即ES2019
ES2019与ES6在词法环境和执行上下文的内容上是近似的,ES2019在细节上做了部分补充,因此本文直接采用ES2019的标准。你也可以对比两个版本的标准的差异。

执行上下文(Execution Context)

执行上下文是用来跟踪记录代码运行时环境的抽象概念。每一次代码运行都至少会生成一个执行上下文。代码都是在执行上下文中运行的。

你可以将代码运行与执行上下文的关系类比为进程与内存的关系,在代码运行过程中的变量环境信息都放在执行上下文中,当代码运行结束,执行上下文也会销毁。

在执行上下文中记录了代码执行过程中的状态信息,根据不同运行场景,执行上下文会细分为如下几种类型:

  • 全局执行上下文:当运行代码是处于全局作用域内,则会生成全局执行上下文,这也是程序最基础的执行上下文。
  • 函数执行上下文:当调用函数时,都会为函数调用创建一个新的执行上下文。
  • eval执行上下文:eval函数执行时,会生成专属它的上下文,因eval很少使用,故不作讨论。

执行栈

有了执行上下文,就要有合理管理它的工具。而执行栈(Execution Context Stack)是用来管理执行期间创建的所有执行上下文的数据结构,它是一个LIFO(后进先出)的栈,它也是我们熟知的JS程序运行过程中的调用栈。
程序开始运行时,会先创建一个全局执行上下文并压入到执行栈中,之后每当有函数被调用,都会创建一个新的函数执行上下文并压入栈内。

我们从一小段代码来看下执行栈的工作过程:

<script>
    console.log('script')    function foo(){
             function bar(){
                 console.log('bar', isNaN(undefined))        }        bar()        console.log('foo')    }    foo()
</script>

当这段JS程序开始运行时,它会创建一个全局执行上下文GlobalContext,其中会初始化一些全局对象或全局函数,如代码中的console,undefined,isNaN。将全局执行上下文压入执行栈,通常JS引擎都有一个指针running指向栈顶元素:

JS引擎会将全局范围内声明的函数(foo)初始化在全局上下文中,之后开始一行行的执行代码,运行到console就在running指向的上下文中的词法环境中找到全局对象console并调用log函数。

PS:当然,当调用log函数时,也是要新建函数上下文并压栈到调用栈中的。这里为了简单流程,忽略了log上下文的创建过程。

运行到foo()时,识别为函数调用,此时创建一个新的执行上下文FooContext并入栈,将FooContext内词法环境的outer引用指向全局执行上下文的词法环境,移动running指针指向这个新的上下文:

在完成FooContext创建后,进入到FooContext中继续执行代码,运行到bar()时,同理仍需要新建一个执行上下文BarContext,此时BarContext内词法环境的outer引用会指向FooContext的词法环境:参考 前端进阶面试题详细解答

继续运行bar函数,由于函数上下文内有outer引用实现层层递进引用,因此在bar函数内仍可以获取到console对象并调用log

之后,完成barfoo函数调用,会依次将上下文出栈,直至全局上下文出栈,程序结束运行。

执行上下文的创建

执行上下文创建会做两件事情:

  1. 创建词法环境LexicalEnvironment
  2. 创建变量环境VariableEnvironment

因此一个执行上下文在概念上应该是这样子的:

ExecutionContext = {
   
  LexicalEnvironment = <ref. to LexicalEnvironment in memory>,
  VariableEnvironment = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值