深入理解JavaScript引擎对于脚本的处理
目录
脚本处理模型
javascript的基本特点
脚本处理模型
源码处理
函数解析
代码执行
脚本处理模型
javascript的基本特点
- js是一门相当简单的运行时解释语言。
- 对象模型很直接也没有类的概念。
- 有自动垃圾回收。
- 弱数据类型。
- 动态类型(dynamic typing):运行的时候才确定对象的类型。
- javascript没有内置的I/O机制。
扩展:javascript程序与宿主环境进行交互,是通过一系列预定义的方法和属性实现的,这些方法和属性会再映射成浏览器的内部原生代码,所以与其他很对常规的编程语言不同,浏览器开放的这些借口往往受限且有针对性。
脚本处理模型
首先,无论是独立的窗口还是在框架里面,每个展示在浏览器里面的html文档,都被赋予了一个独立的javascript执行环境实例,在这个环境里面加载的脚本的所有全局变量和函数都拥有一个独立的命名空间。
然后,同一个文档的所有脚本都运行在同一个执行环境里面,共享同一个沙箱,并且能够通过浏览器提供的API与其他上下文环境交互。
最后:在特定的执行上下文里面,每段javascript代码块都是自成体系处理的,顺序也基本确定。每段代码块都是由若干符合语法格式的独立单元组成,处理的过程包括清晰而且连续的三个步骤:源码处理,函数解析,代码执行。
源码处理
源码处理阶段会检查脚本代码块里面的语法,通常会先把代码转换成中间层的二进制映像,这样才能或得到令人满意的执行速度。在彻底完成这一步骤之前,这些二进制代码对全局并无影响。如果源码处理阶段出错,整个有问题的代码块都会被弃用;然后解析器会继续处理下一段代码块。
函数解析
完成了上一步骤之后,接下来就是解析器对当前代码块里所有具名的全局函数进行识别并注册。在这一阶段完成之后,这些函数才能被执行代码所调用。
对于代码
<script>
hello_world();
function hello_world(){
console.log('hello, man');
}
</script>
因为javascript在执行前会额外预处理,因此上面的写法会成功执行。
而对于代码
<script>
hello_world();
</script>
<script>
function hello_world(){
console.log('hello, man');
}
</script>
对于这段代码会因为运行的时候错误而执行失败,因为代码里每段独立的代码块并不是同时处理的,这是根据javascript引擎读取代码块的先后顺序决定的。在执行第一个代码块的时候,定义hello_world()的那块代码块还没有被解析呢。
再看代码
<script>
hello_world();
var hello_world = function(){
console.log('hello, men');
}
</script>
出现这个现象的原因是:在调用hello_world()的时候,对于hello_world变量的赋值还没有开始呢!
解释:javascript这种全局名称解析模型只针对于函数有效,而对于变量的声明却并非如此。与其他脚本语言类似,变量是按照执行的时候出现的顺序注册的。
推荐阅读: