摘要:解析与编译从源程序到可以被计算机识别的目标程序主要包含两个阶段解析生成抽象语法树编译执行解析以引擎为例,前置的解析被分为两种类型。解释器就像口译员,从源代码第一行开始进行解析编译执行。
解析与编译
Javascript 从源程序到可以被计算机识别的目标程序主要包含两个阶段:
解析生成抽象语法树
编译执行
解析以V8引擎为例,前置的解析被分为两种类型:Pre-Parser、Full-Parser。
Pre-Parser,主要负责对整个 Javascript 源代码进行必要的前期检查,判断是否存在语法错误。只在 Top-level 代码执行前进行。
这里是一种比较普遍的流程,在使用某个事物之前,靠谱的做法当然是先明确下能不能用。
Full-Parser,做的工作相应比较多些,包含:
通过分词/词法分析、解析/语法分析生成抽象语法树(Abstract Syntax Tree,AST)
进行作用域分析,为变量分配内存,生成可用的上下文作用域。具体包括:
将形参作为 GO/AO 的属性,赋值为实参值
将变量作为 GO/AO 的属性,赋值为 undefind
将函数作为 GO/AO 的属性,赋值为其函数体
创建该函数的作用域链等
GO (Global Object),全局环境下创建全局对象。
AO (Active Object),函数执行前创建激活对象。
Full-Parser,在Top-level代码和非Top-level代码执行前都会进行。函数在被调用执行前,经过Full-Parser生成抽象语法树提供给JIT编译器,生成目标语言执行。
Top-level 是指源代码初次加载时需要被首先运行到的“顶层”代码。
V8引擎不一次性完成 Javascript 源代码对应的 AST 信息,而是在知道要执行哪段代码前,将这段代码完成 AST 的生成。
想要了解 AST 信息,可查看 AST 生成工具。
问题:编译执行:
【1】变量提升的原因是因为为了提高执行效率,在代码执行前Full-Parser阶段为变量分配资源。
【2】函数声明优先于变量声明是因为变量声明只检查变量是否存在,而函数声明需要更新变量值。
在了解JS的编译过程前,先明确两个概念:解释器、编译器。
解释器就像口译员,从源代码第一行开始进行解析编译执行。
编译器则是直接将完整的源代码完全编译生成目标程序,从而快速执行。
解释器与编译器各有各的优势,解释器能够快速启动与执行,浏览器能够快速执行JS代码对Web页面来说是非常重要的,这也是为什么浏览器使用解释器来解析JS源代码。
但是,在使用解释器也存在着一些弊端,比如在处理循环的时候,解释器并没有很好的处理重复的“翻译”工作。所以在早期(2008年以前)JS执行的速度并不是很快。
然而,编译器除了编译时间长一些,可以对代码有更好的优化,从而能够更快的执行代码。因而,在2008年,多种浏览器添加了即时编译器(JIT, just in time),使得JS的执行速度提高了10倍。
那么JIT做了些什么事情呢?
JIT包含两部分构成:
基线编译器
优化编译器
首先源代码会经过基线编译器解析编译生成未优化的目标代码。同时JS引擎有称为监视器/分析器的部件,记录代码执行的次数和方式。
当某段代码执行次数变多时,如函数频繁调用、循环代码块等,基线编译器会对这段代码做一些优化。当这段代码执行次数越来越多,监视器会将这段代码交给优化编译器,从而生成更快的版本。
为了生成更快的版本,优化编译器必须做一些假设,并且生成的代码也是默认这些假设都成立的。但是,如果在代码执行过程中,某个假设失败了,浏览器将执行返回到解释器或者基线编译的版本。
这个过程称为去优化,所以循环中数据类型与结构的变化可能会对优化编译过程造成影响。
具体流程如下:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102002.html
摘要:在动态解析阶段,和会有不同的表现解析为一个预编译语句的参数标记符。其次,在预编译之前已经被变量替换了,这会存在注入问题。预编译语句对象可以重复利用。默认情况下,将对所有的进行预编译。总结本文主要深入探究了对和的不同处理方式,并了解了预编译。 mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: sele...
摘要:启动性能瓶颈分析与解决方案翻译自的,从属于笔者的前端入门与工程实践。我们必须要清醒地认识到全面评测以挖掘出真正性能瓶颈的重要性。这可能是最佳的方式了,类似于这样的模式鼓励基于路由的分组,目前被与广泛使用。 JavaScript 启动性能瓶颈分析与解决方案 翻译自 Addy Osmani 的 JavaScript Start-up Performance,从属于笔者的Web 前端入门与工...
摘要:前言本文内容基本摘抄自深入理解虚拟机,以供复习之用,没有多少参考价值。此区域是唯一一个在虚拟机规范中没有规定任何情况的区域。堆是所有线程共享的内存区域,在虚拟机启动时创建。虚拟机上把方法区称为永久代。 前言 本文内容基本摘抄自《深入理解Java虚拟机》,以供复习之用,没有多少参考价值。想要更详细了解请参考原书。 第二章 1.运行时数据区域 showImg(https://segment...
摘要:高级开发人员可能会仔细分析他们的捆绑包,以帮助确定减少不必要依赖。在运行过程中,长时间运行的可以阻塞主线程导致页面没有响应。然后当最终被取出时,附加事件请注意这有内在的花销。发送一个最小功能的页面包含实行当前功能的。保持低这些问题。 原文 当我们构建的网页大量依赖于Javascript,我们有些时候需要研究那些不太容易看得见的消耗。在这篇文章中,我将介绍为什么一点规则可以帮助如果你想让...
阅读 3763·2021-10-08 10:05
阅读 2926·2021-09-27 13:57
阅读 2637·2019-08-29 11:32
阅读 988·2019-08-28 18:18
阅读 1258·2019-08-28 18:05
阅读 1947·2019-08-26 13:39
阅读 804·2019-08-26 11:37
阅读 2026·2019-08-26 10:37