JavaScript的预编译和执行
Posted 我叫王自信
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript的预编译和执行相关的知识,希望对你有一定的参考价值。
JavaScript引擎,不是逐条解释执行javascript代码,而是按照代码块一段段解释执行。所谓代码块就是使用<script>标签分隔的代码段。
整个代码块共有两个阶段,预编译阶段和执行阶段
一、编译阶段
对于常见编译型语言(例如:Java)来说,编译步骤分为:词法分析->语法分析->语义检查->代码优化和字节生成。
对于解释型语言(例如javascript)来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。
(1)词法分析是将字符流(char stream)转换为记号流(token stream),就像英文句子一个个单词独立翻译。
(2)语法分析得到语法树,举例:
条件语句 if(typeof a == "undefined" ){ a = 0; } else { a = a; } alert(a);
当JavaScript解释器在构造语法树的时候,如果发现无法构造,就会报语法错误,并结束整个代码块的解析。
(3)“function函数”是一等公民!编译阶段,会把定义式的函数优先执行,也会把所有var变量创建,开辟内存空间,默认值为undefined,以提高程序的执行效率!
当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理!并且是先预声明变量,再预定义函数!(变量提升是函数提升在变量提升前).
JavaScript语法采用的是词法作用域(lexcical scope),也就是说JavaScript的变量和函数作用域是在定义时决定的(代码书写决定函数作用域,函数调用执行决定执行上下文和作用域链),而不是执行时决定的,由于词法作用域取决于源代码结构,所以 JavaScript解释器只需要通过静态分析就能确定每个变量、函数的作用域,这种作用域也称为静态作用域(static scope)。
二、JavaScript执行过程
声明一个概念:执行上下文。即当前代码的执行环境,js 的运行环境包括:(1)全局环境(2)函数环境(函数被调用执行时,执行上下文推入函数调用栈)(3)eval,尽量避免使用
例:var color="red";
function getColor(){
var anColor="blue";
function chColor(){
anColor=color;
}
chColor();
}
getColor();
分析:开始函数调用栈栈底为全局上下文,当代码执行到getColor()时,将getColor()推入函数调用栈,执行到chColor()时,将chColor()推入函数调用栈。执行完后依次弹出。(return 可以直接终止代码执行,将当前上下文弹出函数调用栈)
因此,函数在被调用后,产生执行上下文。
产生执行上下文后到代码开始执行前,执行上下文会分别创建变量对象,建立作用域链,确定this指向。
保存内部变量、内嵌函数以及建立arguments对象保存当前上下文参数。构造它的作用域链,搜索函数中用var声明的变量放入该链(在语法分析阶段就已经得到放在语法树中,此时只是拷贝过来),寻找变量时会沿着自身作用域链向上寻找。
如果函数引用了外部变量的值,则JavaScript引擎会为该函数创建一个闭包体(closure),闭包体是一个完全封闭和独立的作用域,它不会在函数调用完毕后就被JavaScript引擎当做垃圾进行回收。闭包体可以长期存在。
代码开始执行,完成变量赋值函数引用执行后续代码。
以上是关于JavaScript的预编译和执行的主要内容,如果未能解决你的问题,请参考以下文章