【问题标题】:pre-parsing and execution context预解析和执行上下文
【发布时间】:2020-09-11 12:11:05
【问题描述】:

我试图更好地理解当 V8 引擎解析代码并为函数定义执行上下文时究竟发生了什么。

大多数 JS 课程和书籍通常讨论的是在“创建阶段”和“执行阶段”发生的事情。 JS引擎使用的语言不同:预解析、解析、AST、基线和优化编译。

根据我目前的阅读理解,虽然我可能非常错误,但“创建阶段”与预解析源代码相同,其中解析器在变量和函数方面做的最少声明以便代码可以运行。例如,在代码中调用函数之前,它不会尝试为函数构建 AST。当从全局范围调用一个函数时,它将被预解析(创建阶段),然后完全解析(执行阶段)。在预解析期间将创建一个具有词法环境等的新执行上下文。然后将对每个嵌套函数重复此过程。

问题 1:我的假设是否正确?正在预解析===创建阶段。 问题2:这是我最不清楚的一点。预解析是否为尚未调用的函数创建函数对象。就是下面调试器的Chrome开发工具中显示的函数对象,实际上是单独基于预解析创建的。参数和调用者属性是否只是在后续执行阶段更新。

let fun1 = function(name){
    let newname="Tom";
    console.log(name, newname);
    };
debugger
fun1("John");

//fun1 函数在它被调用之前出现在开发工具中(并且可能在它被添加到执行堆栈之前) 脚本 fun1:ƒ(名称) 参数:空 来电者:空 长度:1 名称:“乐趣1” 原型:{构造函数:ƒ} 原型:ƒ ()

//fun1函数被调用后加入执行栈。 当地的 名称:“约翰” 新名称:未定义 这个:窗口 脚本 fun1:ƒ(名称) 参数:参数 [“John”,被调用者:ƒ,符号(Symbol.iterator):ƒ] 来电者:空 长度:1 名称:“乐趣1” 原型:{构造函数:ƒ} 原型:ƒ ()

【问题讨论】:

  • 创建阶段”是指在函数调用期间创建变量范围。它与“(预)解析”完全无关。

标签: javascript parsing v8


【解决方案1】:

大多数 JS 课程和书籍通常讨论的是......

我不知道“大多数 JS 课程和书籍”,并且该参考资料不够具体,无法查找。如果您想与某处的特定术语用法进行特定比较,请指定您所指的来源。

当一个函数在全局范围内被调用时,它会被预解析(创建阶段),然后被完全解析(执行阶段)。

预解析仅在函数被调用或完全解析之前(很长时间)发生时才有用——这就是它被称为 pre- 解析的原因。 解析不是执行的一部分。解析发生在编译的第一步(或者你可以说:“在编译之前”;同样的事情),这必须在执行开始之前发生。 (至少在现代高性能引擎中是这样的;您可以构建一个不编译任何内容但直接解释源代码的引擎,这意味着有效解析和执行将是同一件事,但那将是 much除了琐碎的脚本之外的所有东西都慢。)

问题 1:我的假设是否正确?正在预解析===创建阶段。

一般来说,JS 执行的高级概念阶段与引擎内部的实现细节之间没有密切的对应关系。

预解析是(部分)完全可选的性能增强实施策略。如果需要,您可以将其关闭 - 事情会变慢,但可观察到的行为将是相同的。基本思想是引擎将“懒惰地”生成代码,即第一次调用函数时(因为预先“急切地”生成所有代码会导致令人讨厌的缓慢启动)。为了能够做到这一点,它必须解决“这里有几百千字节的JS代码,请编译function fun1”的问题,所以它必须知道“fun1”在哪里。这就是“预解析”步骤生成的信息:它基本上创建了一个索引映射函数名称到源文本中定义相应函数的位置。

(作为另一种完全可选的性能增强实现策略,现代引擎对内部变量表示/分配做出了复杂的选择,为了产生正确的行为,需要预先解析以生成有关从其他函数引用的变量的附加数据;所以如果您查看实现,您会发现它比识别function <name> { ... } 范围要复杂得多。您是正确的,预解析不会构建 AST,但是出于这个原因,它确实构建了范围链。)

问题2:预解析是否为尚未调用的函数创建函数对象。

预解析、完整解析和编译都只会影响函数的代码。它们与函数对象本身无关。当你有一个函数对象时,你一般无法判断它是否被预解析,它的代码是否被编译,或者它的代码是否被优化(=再次编译,稍后,将类型反馈带入帐户)与否。函数对象是通过执行相应的外部函数(可能是全局范围内的代码)来创建的。它具有对其执行所需的元数据(代码和其他)的内部隐藏引用。

再次强调这一点:关于何时执行引擎解析/编译的所有细节都是内部实现细节,这些细节在引擎之间是不同的,并且随着时间的推移而变化(随着各自团队改进他们的引擎),所以他们通常不得影响程序的执行方式。

【讨论】:

    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    相关资源
    最近更新 更多