理解JavaScript的编译过程与运行机制

2023-11-08

 JavaScript引擎,不是逐条解释执行javaScript代码,而是按照代码块一段段解释执行。所谓代码块就是使用<script>标签分隔的代码段。

一、编译阶段

对于常见编译型语言(例如:Java)来说,编译步骤分为:词法分析->语法分析->语义检查->代码优化和字节生成。

对于解释型语言(例如JavaScript)来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。

(1)词法分析是将字符流(char stream)转换为记号流(token stream),就像英文句子一个个单词独立翻译,举例:

代码:var result = testNum1 - testNum2; 

词法分析后 :

  1. NAME "result"  
  2. EQUALS  
  3. NAME "testNum1"  
  4. MINUS  
  5. NAME "testNum2"  
  6. SEMICOLON 

(2)语法分析得到语法树,举例:

条件语句 if(typeof a == "undefined" ){ a = 0; } else { a = a; } alert(a);

 

当JavaScript解释器在构造语法树的时候,如果发现无法构造,就会报语法错误,并结束整个代码块的解析。

(3)“预编译”(并非完全的顺序执行)

“function函数”是一等公民!编译阶段,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率!

总结:当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理!并且是先预声明变量,再预定义函数!

二、JavaScript执行过程

 在解释过程中,JavaScript引擎是严格按着作用域机制(scope)来执行的。JavaScript语法采用的是词法作用域(lexcical scope),也就是说   JavaScript的变量和函数作用域是在定义时决定的,而不是执行时决定的   ,由于词法作用域取决于源代码结构,所以 JavaScript解释器只需要通过静态分析就能确定每个变量、函数的作用域,这种作用域也称为静态作用域(static scope)。补充:但需要注意,with和eval的语义无法仅通过静态技术实现,实际上,只能说JS的作用域机制非常接近lexical scope。

JavaScript中的变量作用域在函数体内有效,无块作用域;

function func(){
    for(var i = 0; i < array.length; i++){  
       //do something here.  
    }  
    //此时i仍然有值,及I == array.length  
    print(i);//但在java语言中,则无效
}

    JavaScript引擎在执行每个函数实例时,都会创建一个执行环境(execution context)。执行环境中包含一个调用对象(call object), 调用对象是一个scriptObject结构(“运行期上下文”),用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析 结构(注意:varDecls和funDecls等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到 scriptObject上)。scriptObject是与函数相关的一套静态系统,与函数实例的生命周期保持一致,函数执行完毕,该对象销毁。

    JavaScript引擎通过作用域链(scope chain)把多个嵌套的作用域串连在一起,并借助这个链条帮助JavaScript解释器检索变量的值。这个作用域链相当于一个索引表,并通过编号来存 储它们的嵌套关系。当JavaScript解释器检索变量的值,会按着这个索引编号进行快速查找,直到找到全局对象(global object)为止,如果没有找到值,则传递一个特殊的undefined值。

案例分析:

var scope = "global";
scopeTest();
function scopeTest(){  
    alert(scope);  
    var scope = "local";  
    alert(scope);  
}

 

打印结果:undefined,local;

分析:省略词法分析等过程...执行遇到函数调用scopeTest(),创建一个调用对象(运行期上下文,函数执行完毕,该对象销毁),构造它的作用域链时,搜索函数中用var声明的变量放入该链(在语法分析阶段就已经得到放在语法树中,此时只是拷贝过来),因此scope在整个函数scopeTest内都是可见的(从函数体的第一行到最后一行)。虽然函数scopeTest的作用域链上有全局对象,自然能够访问到全局的scope,但寻找变量时会沿着自身作用域链向上逐个找,因此首先找到自己的scope:undefined。 

    如果函数引用了外部变量的值,则JavaScript引擎会为该函数创建一个闭包体(closure),闭包体是一个完全封闭和独立的作用域,它不会在函数调用完毕后就被JavaScript引擎当做垃圾进行回收。闭包体可以长期存在,因此开发人员常把闭包体当做内存中的蓄水池,专门用来长期保存变量的值。只有当闭包体的外部引用被全部设置为null值时,该闭包才会被回收。当然,也容易引发垃圾泛滥,甚至出现内存外溢的现象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解JavaScript的编译过程与运行机制 的相关文章

随机推荐

  • 学生成绩管理系统

    学生实体 属性由学号 姓名 性别 出生日期 地区 民族组成 班级实体 属性由班级编码 班级名称 院系 年级 人数组成 课程实体 属性由课程号 课程名 学分 学时 学期 前置课组成 学时实体选择课程实体 属于多对多关系 学生事宜属于班级实体
  • Vue中使用vuex(五)

    vuex的模块化 命名空间 1 目的 让代码更好维护 让多种数据分类更加明确 2 创建person js import axios from axios import nanoid from nanoid export default na
  • C# Namespace详解

    我现在感到学好C 就是就是要知道C 的基本语法 C 的新的特点 C 能干什么 其中我感到不管如何 NAMESPACE都是很关键的 可以说不是只对C 而言 而是整个 NET都是由NAMESPACE组成的 所以我在看了C 的基本语法后 就直奔N
  • Android常用知识点总结

    一 选择题 1 Android项目中的主题和样式资源 通常放在 C 目录 A res drawable B res layout C res values D assets 2 Dalvik虚拟机属于Android系统架构中的 C A 应用
  • Torchvision.ops.batched_nms() 和 nms()区别

    区别 batched nms 根据每个类别进行过滤 只对同一种类别进行计算IOU和阈值过滤 nms 不区分类别对所有bbox进行过滤 如果有不同类别的bbox重叠的话会导致被过滤掉并不会分开计算 Torchvision ops nms 参数
  • 干货!人体姿态估计与运动预测

    点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入 我们人类具有识别人体姿态 预测短期未来的能力 例如在走路时我们会识别对向行人的姿态 根据对他们未来运动的预测来决定往左走还是往右走 在打篮球或踢足球时会根据对防守球员的姿态 运动
  • ASP.NET Core学习路线图

    说明 1 先决条件 C https www pluralsight com paths csharp Entity Framework https www pluralsight com search q entity 20framewor
  • 最新的ssm毕业设计题目50例

    ssm毕业设计题目1 10题 1 基于SSM的车险管理系统设计与实现 2 基于SSM框架的学子商城系统的设计与实现 3 基于SSM的高校排课系统的研究与应用 4 基于SSM的湖南省入境旅游客源市场结构分析 5 基于SSM模型的重庆制造业主导
  • VOSviewer安装及配置

    VOSviewer安装网址 VOSviewer Download 根据自己电脑安装 并且VOSviewer要求JAVA 使用的是1 8 0 https www oracle com technetwork java javase downl
  • 关于maven <dependencyManagement>标签的问题

    项目场景 我giao 大家好跟大家分享一个使用maven时发现的小问题 关于父工程pom文件中 dependencyManagement 标签的问题 问题描述 在新建夫工程pom文件时 在内部的依赖不会马上到中央仓库中去下载jar包 而是在
  • 李宏毅-DeepLearning-2017-Unsupervised Learning:Neighbor Embedding

    数据降维的方法 Manifold Learning 流行学习 1 什么是流形 流形学习的观点 认为我们所能观察到的数据实际上是由一个低维流行映射到高维空间的 由于数据内部特征的限制 一些高维中的数据会产生维度上的冗余 实际上这些数据只要比较
  • 将一台笔记本电脑作为另一台笔记本电脑的扩展显示器

    步骤 步骤1 打开设置 可以使用 快捷键win i 打开设置 然后点击 系统 步骤2 点击 投影到此电脑 可以看到右边的选项是灰色 不可以选 然后点击 可选功能 如果是可选的 可以跳过步骤4 步骤3 查找是否安装了 无线显示器 如果没有安装
  • 【机器学习】Tensorflow概率编程:线性混合模型

    线性模型是我们最常见到的 最理想的数学模型 基本的线性模型是数据科学入门的基本案例 然而现实生活中的线性问题 很大几率不适用于基本的线性模型 需要使用线性混合模型来描述 Tensorflow edward提供对这类问题的解决方案 大部分数据
  • 记一次文件因content-type问题无法打开的经历

    记一次文件因content type问题无法打开的经历 引 场景 方案 Jsoup的Content Type simplemagic file can t open 流不可重复消费问题 Tika 总结 引 在Http请求头和响应头都有这个a
  • 什么是 Scrum 工件?

    What is Scrum Artifacts 随着我们的技术系统和项目在规模和复杂性方面不断发展 Scrum 会议和敏捷方法已成为许多公司开发过程中不可或缺的一部分 Scrum 会议是团队成员协作的好方法 可确保队列中的所有项目和任务都得
  • IBM RATIONAL BUILDFORGE入门

    最近在项目中使用了BUILDFORGE作为自动化部署工具进行项目的自动化部署 在此写下自己在该工具中入门的心得 1 首先需要建立服务器认证 可以为多台服务器设置相同的一个服务器认证 用该认证中的用户名和密码去登录服务器 2 其次建立服务器
  • Redis的RDB和AOF两种存储方式

    Redis其实就是一个用C语言写的一个程序 这个程序用来存储 key value数据 数据先放在内存 然后写入磁盘指定位置 这么理解十分肤浅 但tm好像就是这样啊 下面我们梳理一下Redis存储两种方式 RDB和AOF 第一种方式 RDB
  • Python求水仙花数

    水仙花数 Narcissistic Number 是一个三位数 其各位数字的立方和等于该数本身 例如 153 1 3 5 3 3 3 因此153是一个水仙花数 以下是一个简单的Python代码来找出所有的水仙花数 python def is
  • python数据分许基础

    1 单选题 单选题 下列关于数据和数据分析的说法正确的是 A 数据就是数据库中的表格 B 文字 声音 图像这些都是数据 C 数据分析的数据只能是结构化的 D 数据分析不可能预测未来几天的天气变化 正确答案 B 文字 声音 图像这些都是数据
  • 理解JavaScript的编译过程与运行机制

    JavaScript引擎 不是逐条解释执行javaScript代码 而是按照代码块一段段解释执行 所谓代码块就是使用