JS执行解释阶段的词法分析会创建词法环境吗?

新手上路,请多包涵

看一些文章说词法分析会创建词法环境如下图但执行阶段才开始创建执行上下文,进而创建的词法环境吧!有大佬知道这个图是否正确吗?创建词法环境是在解释阶段还是执行阶段?

阅读 1.7k
3 个回答

个人还是认为应该是在执行阶段创建词法环境,解释阶段并不会直接创建执行上下文,而进入不同的上下文会创建不同的词法环境

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。

执行环境/执行上下文和词法环境都是纯粹的规范机制,不需要对应于一个ECMAScript的特定实现。

规范中说
1、任何时候,当控制器从当前运行的执行环境相关的可执行代码转入与该执行环境无关的可执行代码时,会创建一个新的执行环境
2、一个词法环境由一个环境记录项和可能为空的外部词法环境引用构成。通常词法环境会与特定的 ECMAScript 代码诸如 FunctionDeclaration,WithStatement 或者 TryStatement 的 Catch 块这样的语法结构相联系,且类似代码每次执行都会有一个新的语法环境被创建出来。

规范中所说的代码执行时被创建对应到js就是函数执行、函数被调用的时候。

但是,单纯的js代码电脑cpu是不认识的,所以他在底层实现会有一个解释执行的过程,这个过程就跟名字一样两个步骤,一是解释阶段,也可以叫解析、编译,编译器将js代码编译为字节码或机器码,这也是执行环境/执行上下文和词法环境被创建的阶段,二是执行阶段,就是执行字节码或机器码。这个执行和js中的函数执行,名字一样,但意义不一样,这也是这个概念网上讲的很混乱的一个原因。

https://262.ecma-international.org/5.1/#sec-10.3
https://www.w3cschool.cn/wsqzg/wsqzg-r4em25o7.html
https://www.w3cschool.cn/wsqzg/wsqzg-n8xi25o6.html

先说结论:
执行上下文是在编译阶段(你所说的解析阶段)创建的。
更准确的说,全局执行上下文,是在js引擎启动后,代码还没开始解析前就被创建了。
函数执行上下文,是在函数被调用后才创建的,但同时也是在函数体内代码的编译阶段创建的。

先搞清楚,【词法环境】只是一种规范类型,【执行上下文】才是规范层面的“具体的东西”,它里面包括【词法环境组件】和【变量环境组件】,这两个组件的类型是【词法环境】。

【执行上下文】是何时创建的,要根据代码类型来看。

Evaluation of global code or code using the eval function (15.1.2.1) establishes and enters a new execution context. Every invocation of an ECMAScript code function (13.2.1) also establishes and enters a new execution context

以上是 ECMA5.1 规范中的原文:
解析执行全局代码或eval()函数内的代码会创建并进入新的可执行上下文。
函数被调用的时候也会创建并进入新的执行上下文。

当然这只是规范文档,具体实施还要看js引擎是怎么做的,可能会与文档说法略有差异。
以v8引擎为例:
全局执行上下文:v8引擎启动后,在开始解析代码前,会做一系列准备工作,其中就包括初始化全局执行上下文。全局执行上下文是在这个时候就被创建了,并且一些内置方法、全局对象等信息也在这时在全局执行上下文中生成。

函数执行上下文:由于【惰性解析】技术,v8引擎在解析代码时,当遇到函数声明代码,不会解析函数内的代码,会将函数代码以字符串的形式存储在内存中,当解析器解析到调用该函数时,才会从内存中取出函数代码字符串,再送入解析器开始解析,这时候才会创建函数的执行上下文,但它也是在解析阶段创建的。

楼主看这块的知识时,建议一个是看ECMA规范文档,另一个是看v8引擎的知识,尽量去看官方文档或者正规机构的付费内容,不要轻信各种社区的帖子,我看过了不是没说清楚就基本都是错的。

你换个角度想,ES采用静态作用域,作用域是编译时就确定的。执行上下文作为ES规范的作用域实现,那肯定也是编译阶段就确定了啊,那创建肯定是在编译阶段或者更前了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题