文档章节

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

二分之一
 二分之一
发布于 2014/03/19 07:55
字数 1291
阅读 831
收藏 1

    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值时,该闭包才会被回收。当然,也容易引发垃圾泛滥,甚至出现内存外溢的现象。





© 著作权归作者所有

共有 人打赏支持
二分之一
粉丝 12
博文 29
码字总数 9595
作品 0
唐山
程序员
私信 提问
通过DLS解析器,了解JS的编译原理

接触Javascript很长一段时间了,但一直浮在语言的表面,今天决定重头开始更深入的学习Javascript,先从Javascript的编译原理开始。 在程序的执行方式中有编译型和解释型,以前学习的C语言就是...

tryzf
06/30
0
0
Vue.js异步更新及nextTick

写在前面 前段时间在写项目时对nextTick的使用有一些疑惑。在查阅各种资料之后,在这里总结一下Vue.js异步更新的策略以及nextTick的用途和原理。如有总结错误的地方,欢迎指出! 本文将从以下...

Jee
08/29
0
0
Vue 全家桶,深入Vue 的世界

FinGet 26 日志 9 分类 15 标签 RSS GitHub E-Mail SegmentFault 推荐阅读 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理 前端进阶系列 八段代码彻底掌握 Promise 通俗大白话来理解...

FinGet
07/02
0
0
记一次寻找Bug的经历-重新理解javascript原型和程序员瓶颈

记一次寻找Bug的经历 今天下午的时候,同事说发现了一个问题.Ext4做好页面,重新单击菜单动态加载一次,树就消失了.于是,我帮忙看了一下,一开始没认为是什么大问题.但是越调发现越不对.到快下班...

架构梦想
2014/04/04
0
0
Node.js Event Loop与浏览器 Event Loop(事件环)

要理解Event Loop首先要学习几个概念,下面就通过这些概念来一步步解析Event Loop 一:进程与线程 进程是操作系统分配资源和调度任务的基本单位,线程是建立在进程上的一次程序运行单位,一个...

张文梦
06/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java 源代码和 C 源代码的运行区别

与其他程序的执行方式和编译方式不同。 Java 源代码需要进行编译成字节码后在 Java 虚拟机上运行,这样 Java 程序能够保持独立性和跨平台功特性。 请参考下图。 https://www.cwiki.us/pages...

honeymose
48分钟前
3
0
Apache限定目录解析PHP,限制user_agent,PHP相关的配置

Apache限定目录解析PHP 配置前访问upload/index.php [root@test-a ~]# curl -x192.168.77.139:80 'www.test.com/upload/index.php'This is upload diretory 配置,/usr/local/apache2.4/......

野雪球
今天
5
0
java.util.Concurrent.Exchanger源码

类图 源码: package java.util.concurrent;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.atomic.AtomicReference;import java.util.concurrent......

狼王黄师傅
今天
6
0
Kubernetes里的secret最基本的用法

Secret解决了密码、token、密钥等敏感数据的配置问题,使用Secret可以避免把这些敏感数据以明文的形式暴露到镜像或者Pod Spec中。 Secret可以以Volume或者环境变量的方式使用。 使用如下命令...

JerryWang_SAP
昨天
5
0
2018-11-20学习笔记

1. python数据类型: 给变量赋值什么样的值,变量就是什么样的类型 给变量赋值整数,变量就是整数类型 给变量赋值字符串,变量就是字符串类型 123 和“123”一样吗? 在python中 单引号 与双...

laoba
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部