深入理解JavaScript之---(JavaScript的编译过程)
来源:互联网 发布:大连软件学校 编辑:程序博客网 时间:2024/06/05 16:42
上周团队代码走读的时候,keke给我的代码提了一个建议:变量声明的时候所有的变量都要在使用前声明,虽然JavaScript没有强制要求这么做,但是这么做可以让程序易于阅读,容易发现那些没有声明的变量。
他还提到JavaScript会预先给变量分配内存,这到底是怎么回事呢?这激起了我的好奇心,要想真正的理解一门语言不仅要知其然还要知其所以然。通过查找资料终于有所理解了。
编程语言有编译语言和解释语言之分。不管是什么语言都要先翻译成机器可以识别的语言,编译语言和解释语言只是翻译成机器语言的时间不同而已。(我看到过一个有趣的比喻:编译语言就像是先做好一桌子菜然后再开吃,解释语言就像是吃火锅,边煮边吃,很耗时的哟)。
编译语言指的是代码在执行之前会先编译成可执行文件,可执行文件就是计算机可以识别的机器语言,即二进制文件(这些可执行文件是一次编译所得,但是可以多次使用),有了可执行文件之后计算机就可以识别这些可执行文件,从而实现高级语言所编写的代码的功能。很明显,编译语言的优点就是执行速度快,缺点是跨平台性差(因为不同的平台对可执行文件的要求不一样,也就是所需要的编译器不一样),C、C++就是典型的编译语言。
解释语言就不会先编译成可执行文件,而是一边把高级语言解释(编译、翻译)成机器语言一边执行代码。优点是:不依赖平台,会根据不同的平台对代码语句进行解释;缺点是:执行速度慢。
现在因为高级语言的种类越来越多,这两个概念都很模糊了,我们已经没必要纠结一门语言到底是属于编译语言还是解释语言。我比较赞同“重要的是语言的工作机理而不是下定义”的观点,透过现象看本质,理解JavaScript的工作机制才是王道。
首先了解一下传统的编译语言的源代码在执行之前经历的三个步骤(编译过程):
1.分词(词法分析)。编译器会将代码(由字符组成的字符串)分解成有意义的代码块,也就是词法单元。例如,程序var a=1;这段程序会被分解成为这些词法单元:var、a、=、2、;。空格是否会被当做词法单元,取决于空格在这门语言中是否具有意义。
2.解析(语法分析)。这个过程是将词法单元流(由上一个步骤分解出来的词法单元组成)转换为由元素逐级嵌套所组成的结构树,它代表的是程序的语法结构,被称为“抽象语法树(AST)”。(这些都是编译原理的知识,要深入研究可以参考一些著名的大学教材)
3.代码生成。这个过程将AST树转换为可执行代码也就是一组机器指令,这个过程和使用的平台有密切的关系。
JavaScript引擎比起以上三个步骤来说要复杂很多,这需要进一步的学习理解。此篇博客只是初学者的一点学习记录。
JavaScript的编译过程不是发生在程序整体执行之前的,也就是说按照编译语言和解释语言分类的话,JavaScript属于解释语言,它没有生成可执行文件的这一过程。所以JavaScript的执行过程是比较慢的,有的JavaScript引擎为了改善它的执行速度就使用JIT技术(just in time)来保证它的性能,(这里稍微提一下,JavaScript引擎是搜索引擎功能的一部分,因为不同的搜索引擎自己编写的JavaScript引擎不同,所以这里就又有一个JavaScript的兼容性问题)。
现在不得不提出三个重要的名词:引擎(从头到尾负责整个JavaScript程序的编译及执行过程)、编译器(负责语法分析及代码生成,不清楚的参看前面的编译过程)、作用域(是一套用于确定在哪里查找变量及如何查找变量的规则) 。了解他们有助于理解JavaScript的工作机制。
以 var a=1;这段程序为例看编译器的执行过程:1.遇到var a,编译器会首先在同一个作用域的集合中寻找该名称的变量,如果有,编译器会忽略该声明,继续进行编译;如果没有,编译器会在当前作用域的集合中声明一个新的变量,命名为 a 。2.接下来编译器会为引擎生成运行时需要的代码,用来处理a=1这个赋值操作。引擎运行时会在当前作用域集合中查找一个叫做a的变量,如果有引擎就会使用这个变量;如果没有,引擎会继续向上一级作用域查找,如果引擎最终找到了变量a,就会将1赋值给它,否则引擎就会抛出一个异常。
(也就是说变量的赋值操作执行的是两个动作)
关于JavaScript的内部机制还有很多,未完待续......
这篇博客对JavaScript的工作流程总结的很清楚http://blog.csdn.net/cxiaokai/article/details/7552653
- 深入理解JavaScript之---(JavaScript的编译过程)
- 理解JavaScript的编译过程与运行机制
- Javascript之this关键字的深入理解
- 深入理解javascript之原型
- 深入理解javascript之this
- 深入理解javascript之函数
- 深入理解javascript之arguments
- 深入理解javascript之继承
- 深入理解javascript之IIFE
- Javascript深入理解之this
- JavaScript深入理解之对象
- JavaScript深入理解之原型
- javascript笔记:深入理解javascript的function
- 【JAVASCRIPT】深入理解JavaScript的闭包
- JavaScript的事件深入理解
- javascript 对象的深入理解
- 深入理解javascript的bind
- 深入理解JavaScript的Promise
- Linux下安装FTP服务器及配置
- 事件总线EventBus(一) GitHub简介
- HDU 1878.欧拉回路【欧拉路及欧拉回路初接触】【8月2】
- UCGUI Deom程序使用vs2010编译提示找不到libc.lib
- EasyUi 日历组件 datebox 开始时间与结束时间限制高级版
- 深入理解JavaScript之---(JavaScript的编译过程)
- CSS 列表属性允许你放置、改变列表项标志,或者将图像作为列表项标志。
- 笔记——float型数据的int引用
- 模拟-POJ-3087-Shuffle'm up
- 操作符(operator)
- 深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件
- equals()方法和“==”的区别
- MATLAB 归一化 函数用法以及实例
- 暑假第2周周报