JavaScript运行原理分析


Posted in Javascript onFebruary 09, 2018

JavaScript是一种基于对象的动态、弱类型脚本语言(以下简称JS),是一种解释型语言,和其他的编程语言不同,如java/C++等编译型语言,这些语言在代码执行前会进行通篇编译,先编译成字节码(机器码)。然后在执行。而JS不是这样做的,JS是不需要编译成中间码,而是可以直接在浏览器中运行,JS运行过程可分为两个阶段,编译和执行。(可参考你不知道的JS这本书),当JS控制器转到一段可执行的代码时(这段可执行代码就是编译阶段生成的),会创建与之对应的执行上下文(Excution Context简称EC)。执行上下文可以理解为执行环境(执行上下文只能由JS解释器创建,也只能由JS解释器使用,用户是不可以操作该‘对象'的)。

JS中的执行环境分为三类:

  • 全局环境:当JS引擎进入一个代码块时,如遇到<script>xxx</script>标签,就是进入一个全局执行环境
  • 函数环境:当一个函数被调用时,在函数内部就形成了一个函数执行环境
  • eval():把字符串单做JS代码执行,不推荐使用

在一段JS代码中可能会产生多个执行上下文,在JS中用栈这种数据结构来管理执行上下文,栈的特点是“先进后出,后进先出”,这种栈称之为函数调用栈。

执行上下文的特点

  • 栈底永远是全局执行上下文,有且仅有一个
  • 全局执行上下文只有在浏览器关闭时,才会弹出栈
  • 其他的执行上下文的数量没有限制
  • 栈顶永远是当前活动执行上下文,其余的都处于等待状态中,一旦执行完毕,立即弹出栈,然后控制权交回下一个执行上下文
  • 函数只有在每次被调用时,才会为其创建执行上下文,函数被声明时是没有的。

执行上下文可以形象的理解为一个普通的JS对象,一个执行上下文的生命周期大概包含两个阶段:

创建阶段

此阶段主要完成三件事件,1、创建变量对象 2、建立作用域链 3、确定this指向

执行阶段

此阶段主要完成变量赋值、函数调用、其他操作

变量对象(VO)的创建过程

  • 1、根据函数参数,创建并初始化arguments对象,给arguments对象添加属性"0","1","2","3"等属性,其初始值为undefined,并设置arguments.length值为实际传入参数的个数。
  • 2、查找function函数声明,在变量对象上添加属性,属性名就是函数名,属性值就是函数的引用值,如果已经存在同名的,则直接覆盖
  • 3、查找var变量声明(查找变量时,会把函数的参数等价于var声明,所以在VO中也会添加和参数名一样的属性,初始值也是undefined),在变量对象添加属性,属性名就是变量名,属性值是undefined,如果已经存在同名的,则不处理

如果存在同名标识符(函数、变量),则函数可以覆盖变量,函数的优先级高于变量

变量对象(OV)和激活对象(AO)是同一个东西,在不同时期的两种叫法。在创建时期叫变量对象,在执行时期叫激活对象

以如下代码为例

var g_name="tom";
var g_age=20;
function g_fn(num){
 var l_name="kity";
 var l_age=18;
 function l_fn(){
  console.log(g_name + '===' + l_name + '===' + num);
 }
}
g_fn(10);

编译阶段

当JS控制器转到这一段代码时,会创建一个执行上下文,G_EC

执行上下文的结构大概如下:

G_EC = {
 VO   : {},
 Scope_chain : [],
 this  : {}
}

/* VO的结构大概 */
VO = {
 g_name : undefined,
 g_age : undefined,
 g_fn : <函数在内存中引用值>
}

/* Scope_chain的大概结构如下 */
Scope_chain = [ G_EC.VO ] // 数组中第一个元素是当前执行上下文的VO,第二个是父执行上下文的VO,最后一个是全局执行上下文的VO,在执行阶段,会沿着这个作用域链一个一个的查找标识符,如果查到则返回,否知一直查找到全局执行上下文的VO

/* this */
this = undefined // 此时this的值是undefined

执行上下文一旦创建完毕,就立马被压入函数调用栈中,此时解释器会悄悄的做一件事情,就是给当前VO中的函数添加一个内部属性[[scope]],该属性指向上面的作用域链。

g_fn.scope = [ global_EC.VO ] // 该scope属性只能被JS解释器所使用,用户无法使用

执行阶段

一行一行执行代码,当遇到一个表达式时,就会去当前作用域链的中查找VO对象,如果找到则返回,如果找不到,则继续查找下一个VO对象,直至全局VO对象终止。

此阶段可以有变量赋值,函数调用等操作,当解释器遇到g_fn()时,就知道这是一个函数调用,然后立即为其创建一个函数执行上下文,fn_EC,该上下文fn_EC同样有两个阶段

分别是创建阶段和执行阶段。

在创建阶段,对于函数执行上下文,在创建变量对象时,会多创建一个arguments对象,然后为arguments对象添加属性:"0","1", "2"其初始值为undefined,

  • 查找function函数声明
  • 查找var变量声明
Javascript 相关文章推荐
js文件中调用js的实现方法小结
Oct 23 Javascript
jQuery学习5 jQuery事件模型
Feb 07 Javascript
jQuery中将函数赋值给变量的调用方法
Mar 23 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
Apr 11 Javascript
js Select下拉列表框进行多选、移除、交换内容的具体实现方法
Aug 13 Javascript
js实现单行文本向上滚动效果实例代码
Nov 28 Javascript
jQuery实现下滑菜单导航效果代码
Aug 25 Javascript
常见的javascript跨域通信方法
Dec 31 Javascript
jQuery插件HighCharts绘制2D饼图效果示例【附demo源码下载】
Mar 21 jQuery
关于vue-router路径计算问题
May 10 Javascript
Vue上传组件vue Simple Uploader的用法示例
Aug 25 Javascript
如何解决js函数防抖、节流出现的问题
Jun 17 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
Feb 09 #Javascript
详解如何在项目中使用jest测试react native组件
Feb 09 #Javascript
vue checkbox 全选 数据的绑定及获取和计算方法
Feb 09 #Javascript
mint-ui 时间插件使用及获取选择值的方法
Feb 09 #Javascript
VUE2 前端实现 静态二级省市联动选择select的示例
Feb 09 #Javascript
尝试自己动手用react来写一个分页组件(小结)
Feb 09 #Javascript
在 React、Vue项目中使用SVG的方法
Feb 09 #Javascript
You might like
PHP下几种删除目录的方法总结
2007/08/19 PHP
php的mssql数据库连接类实例
2014/11/28 PHP
PHP编写RESTful接口
2016/02/23 PHP
PHP Smarty模版简单使用方法
2016/03/30 PHP
php readfile()修改文件上传大小设置
2017/08/11 PHP
实例介绍PHP中zip_open()函数用法
2019/02/15 PHP
基于Jquery的仿Windows Aero弹出窗(漂亮的关闭按钮)
2010/09/28 Javascript
jQuery之自动完成组件的深入解析
2013/06/19 Javascript
js脚本实现数据去重
2014/11/27 Javascript
为什么Node.js会这么火呢?Node.js流行的原因
2014/12/01 Javascript
使用Web Uploader实现多文件上传
2016/06/08 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
2016/07/22 Javascript
JavaScript类的写法
2016/09/17 Javascript
JavaScript 随机验证码的生成实例代码
2016/09/22 Javascript
Express系列之multer上传的使用
2017/10/27 Javascript
Nuxt.js实现一个SSR的前端博客的示例代码
2019/09/06 Javascript
微信小程序引入VANT组件的方法步骤
2019/09/19 Javascript
浅谈Vue中render中的h箭头函数
2019/11/07 Javascript
[01:01:18]DOTA2上海特级锦标赛主赛事日 - 2 败者组第二轮#2COL VS LGD
2016/03/03 DOTA
[14:19]2018年度COSER大赛-完美盛典
2018/12/16 DOTA
Python2与python3中 for 循环语句基础与实例分析
2017/11/20 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
Python一行代码实现快速排序的方法
2019/04/30 Python
新手入门Python编程的8个实用建议
2019/07/12 Python
Python如何实现在字符串里嵌入双引号或者单引号
2020/03/02 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
python excel和yaml文件的读取封装
2021/01/12 Python
Python 将代码转换为可执行文件脱离python环境运行(步骤详解)
2021/01/25 Python
医院检讨书范文
2014/02/01 职场文书
国贸专业求职信
2014/06/28 职场文书
教师师德师风整改措施
2014/10/24 职场文书
新年晚会主持词开场白
2015/05/28 职场文书
名人传读书笔记
2015/06/26 职场文书
《语言的突破》读后感3篇
2019/12/12 职场文书
Python深度学习之Pytorch初步使用
2021/05/20 Python
如何自己动手写SQL执行引擎
2021/06/02 MySQL