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 可以直接终止代码执行,将当前上下文弹出函数调用栈)
因此,函数在被调用后,产生执行上下文。
产生执行上下文后到代码开始执行前,执行上下文会分别
- 创建Scope chain
- 创建VO/AO(variables, functions and arguments)
- 设置this的值
对于"创建VO/AO"这一步,JavaScript解释器主要做了下面的事情:
- 根据函数的参数,创建并初始化arguments object
- 扫描函数内部代码,查找函数声明(Function declaration)
- 对于所有找到的函数声明,将函数名和函数引用存入VO/AO中
- 如果VO/AO中已经有同名的函数,那么就进行覆盖
- 扫描函数内部代码,查找变量声明(Variable declaration)
- 对于所有找到的变量声明,将变量名存入VO/AO中,并初始化为"undefined"
- 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性
- 在函数中新建的变量,变量对象中值为undefined
-
function foo(i) {
var a = 'hello';
var b = function privateB() { };
function c() { }
} foo(22);VO
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: undefined,
b: undefined
},
this: { ... }
}AO
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: 'hello',
b: pointer to function privateB()
},
this: { ... }
}
如果函数引用了外部变量的值,则JavaScript引擎会为该函数创建一个闭包体(closure),闭包体是一个完全封闭和独立的作用域,它不会在函数调用完毕后就被JavaScript引擎当做垃圾进行回收。闭包体可以长期存在。
代码开始执行,这个特殊的活动对象(activation object) 就被创建了。它包含普通参数(formal parameters) 与特殊参数(arguments)对象(具有索引属性的参数映射表)。活动对象在函数上下文中作为变量对象使用。完成变量赋值函数引用执行后续代码。
作用域链是一个 对象列表(list of objects) ,用以检索上下文代码中出现的 标识符(identifiers) 。
JavaScript的预编译和执行的更多相关文章
- javascript的预编译和执行顺序
原文:javascript的预编译和执行顺序 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 代码一<html> ...
- JS的预编译和执行顺序 详析(及全局与局部变量)
最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题: <html> <head> <title> ...
- JS的预编译和执行顺序 详析
原文:JS的预编译和执行顺序 详析 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 复制代码 代码一 <ht ...
- 关于JavaScript预编译和执行顺序以及函数引用类型的思考
昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了.问题抽象出来是这样的: <script > ...
- javascript预编译和执行过程总结
javascript相对于其它语言来说是一种弱类型的语言,在其它如java语言中,程序的执行需要有编译的阶段,而在javascript中也有类似的“预编译阶段”(javascript的预编译是以代码块 ...
- JavaScript 之 预编译 作用域,作用域链
第一次写博客,本来是学习jQuery遇到闭包问题,发现并没有理解闭包,发现闭包牵扯的知识点太多.复习了一遍(发现自己该记住的全忘了)写在博客里,自己也是小白,希望大神们指点迷津,必将感激不尽. 我们知 ...
- 一步一步的理解javascript的预编译
首先,我们要知道javascript是单线程.解释性语言.所谓解释性语言,就是翻译一句执行一句.而不是通篇编译成一个文件再去执行. 其实这么说还没有这么直观,读一句执行一句那是到最后的事了.到JS执行 ...
- JavaScript之预编译
javascript是一种解释性弱类型语言,在浏览器中执行时,浏览器会先预览某段代码进行语法分析,检查语法的正确与否,然后再进行预编译,到最后才会从上往下一句一句开始执行这段代码,简单得来说可以表示为 ...
- JS 的预编译和执行顺序
脚本执行js引擎做的工作: 语法分析 预编译 解释执行
随机推荐
- 如何书写优雅、漂亮的SQL脚本?
本篇来聊聊如何书写漂亮.整洁.优雅的SQL脚本,下面这些是我个人总结.整理出来的.姑且做个抛砖引玉吧,呵呵,欢迎大家一起来讨论. 我们首先来看看一段创建数据表的脚本(如下所示),你是否觉得有什么不 ...
- android软键盘的显示和隐藏
显示: InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.toggle ...
- MySQL中, 如何查询某一天, 某一月, 某一年的数据.
今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天(包括昨天和今天的数据) SELECT * FROM 表名 WHERE TO_ ...
- ehcache模糊批量移除缓存
目录 前言 实现 总结 前言 众所周知,encache是现在最流行的java开源缓存框架,配置简单,结构清晰,功能强大.通过注解@Cacheable可以快速添加方法结果到缓存.通过@CacheEvic ...
- NOI2001 食物链
食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种 ...
- JAVA 调用 R 语言之升华篇
由于项目的需要,最近做了一个javaWeb调用R的组件,在这里,我把自己走的一些弯路给大家总结一下: 一.选取什么插件作为java和R之间的通信? 1. 在传统的方式中,大致可以分为两类:一类是JRI ...
- 突然觉得前端js挺不错的
由于工作的需要,现在对前端技术有一定的要求,但是发现普遍前端技术都比较弱,遇到问题基本上没有人能帮助你解决,只好自己学习了. 从事java开发已经好久了,真的是好久了,但是水平一直还是一般吧. 从今天 ...
- Windows远程桌面卡的解决办法
Windows远程桌面卡的解决办法 如果在网络没有什么大问题的情况下,可以尝试以下操作. 1.显示中颜色选择 增强色15位 2.体验中 设置成下图的样子 然后在尝试连接试试有没有好点
- Uva 11077 Find the Permutations [置换群 DP]
题意: 给定$n$和$k$,问有多少排列交换$k$次能变成升序 $n \le 21$ $uva$貌似挂掉了$vjudge$上一直排队 从某个排列到$1,2,...,n$和从$1,2,...,n$到某个 ...
- 小甲鱼OD学习第3讲
这次我们的任务是破解这个过期的软件,效果如图所示 我们通过阅读代码,知道这个程序的执行流程如图中注释所示 观看下图注释所示 这是失败的提示代码 这是成功的提示代码 最后我们可以得出结论,成功破解软件的 ...