游览器中javascript的执行过程(图文)


Posted in Javascript onMay 20, 2012

1. 大多数游览器的组件构成如图     

游览器中javascript的执行过程(图文)

在最底层的三个组件分别是网络,UI后端和js解释器。作用如下:
(1)网络- 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作
(2)UI 后端- 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口
(3)JS解释器- 用来解释执行JS代码

ps:上图和知识点主要来自《HOW BROWSERS WORK: BEHIND THE SCENES OF MODERN WEB BROWSERS》 想深入了解的同学可以重点看下。
2. 大多数游览器(比如chrome)让一个单线程共用于执行javascrip和更新用户界面。这个线程通常被称为“游览器UI线程”, 每个时刻只能执行其中一种操作,这意味着当Javascript代码正在执行时用户界面无法响应输入,反之亦然。这样做是因为javascript代码的作用就是操作DOM更新用户界面,用同一个线程来做负责这两件事情可以更高效
3. 游览器UI线程的工作基于一个简单的队列系统,任务会被保存到队列中直到进程空闲。一旦空闲,队列中的下一个任务就被重新提取出来并运行。这些任务要么是运行javascript代码,要么执行UI更新,包括重绘和重排。
4. 重点再强调下,javascript是单线程运行,千万别被setTimeout()和setInterVal()这种函数迷惑而误以为它是多线程。
ok,基础点讲解完毕,让我们进入正题,来讲解在游览器中javascript的执行过程。
一、原理
一般而言,<script>标签每次出现都会霸道地让页面等待脚本的解析和执行,无论当前的Javascript是内嵌的还是包含了外链文件,页面的下载和渲染都必须停下来等待脚本执行完成。这在页面的生存周期中是必要的,因为脚本执行过程中可能修改页面内容,一个典型的例子就是在页面中使用document.write()。
当javascript代码是内嵌在html里面时,这点还是比较容易理解,但当javascript是外链文件时稍微有点负载,因为存在一个加载过程,而且游览器加载好这个js文件之后往往还对其缓存。
首先,我们用以下这个例子来说明下缓存问题

<html> 
<head> 
<script type='text/javascript' src='js/f2.js'></script> 
</head> 
<body> 
</body> 
</html>

第一次打开页面时:

游览器中javascript的执行过程(图文)

    第二次打开页面时:

游览器中javascript的执行过程(图文)

    从上例中可以明显看出,像chrome之类的高版本游览器会对js文件进行缓存,作用是不言而喻,减少网络请求。

其次,第二个问题,当一个javascript文件被加载时是否会阻塞其他javascript文件或者其他文件的加载。《高性能Javascript》一书中对这个问题做了较好的解答:各种游览器的低版本的处理是当一个javascript文件在加载时,会同时阻塞页面其他文件的加载(包括其他javascript文件),但IE8,Firfox3.5,Safari 4和Chrome 2都允许并行下载javascript文件,但遗憾的是,javascript下载过程仍然会组舍其他资源的下载,比如图片。尽管javascript脚本的下载过程不会相互影响,但页面仍然必须等待所有的javascript代码下载并执行完成才能继续。

这里说句题外话:游览器对同一域名下的并发链接数也是有限制的,其他一些参数如下:
游览器中javascript的执行过程(图文)
二、技巧
1. 脚本位置
由于脚本会阻塞页面其他资源的下载,因此推荐将所有的<script>标签放到<body>标签的底部,已尽量减少对整个页面下载的影响。
2. 将能合并的js文件合并
3. 无阻塞脚本
现在比较常用的方法就是动态加载执行脚本。你的原理是通过DOM,你几乎可以用Javascript动态创建HTML中的所有内容,其根本在于,<script>标签与页面中其他元素并无差异:都能通过DOM引用,都能在文档中移动,删除和创建。文件在改该<script>元素被添加到页面时开始现在,它不会阻止其他文件下载,只在执行阶段阻塞渲染。特别强调:《高性能javascript》一文中说“这种技术的重点在于:无论何时启动下载,文件的下载和执行都不会阻塞页面其他进程”,这并不是说它在执行不会阻塞其他javascript代码,而是要强调不会阻塞其他资源的下载等其他任务。
具体的代码如下:

function loadScript(url){ 
var ga = document.createElement('script'); 
ga.type = 'text/javascript'; 
ga.async = true; 
ga.src = url; 
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga); 
}

4. 神奇的setTimeout()
这里我不过多的将setTimeout()的原理,有兴趣的读者可以具体去看《高性能javascript》的第六章。我重点强调下,setTimeout的第二个参数并不是一个精确的时间,二是必须在javascript线程空闲时才能运行。利用这个特性,如下代码简单可以实现等待其他js代码执行完毕后再执行function里面的代码。
setTimeout(function(){ 
// do some before other javascripe codes had processed 
}, 25)

但在function里面不要使用document.write()方法,因为执行setTimeout里面函数时往往已经到了页面onload之后,此时再执行 document.write 将导致当前页面的内容被清空,因为它会自动触发 document.open 方法。
《高性能Javascript》
HOW BROWSERS WORK: BEHIND THE SCENES OF MODERN WEB BROWSERS
Google Chrome源码剖析【一】:多线程模型
javascript异步加载详解
Javascript 相关文章推荐
基于jQuery的计算文本框字数的代码
Jun 06 Javascript
jQuery之Deferred对象详解
Sep 04 Javascript
JS运动基础框架实例分析
Mar 03 Javascript
Angular ng-repeat指令实例以及扩展部分
Dec 26 Javascript
js学使用setTimeout实现轮循动画
Jul 17 Javascript
使用jQuery实现购物车结算功能
Aug 15 jQuery
用最少的JS代码写出贪吃蛇游戏
Jan 12 Javascript
vue+jquery+lodash实现滑动时顶部悬浮固定效果
Apr 28 jQuery
在Vue项目中用fullcalendar制作日程表的示例代码
Aug 04 Javascript
Vue路由之JWT身份认证的实现方法
Aug 26 Javascript
js中script的上下放置区别,Dom的增删改创建操作实例分析
Dec 16 Javascript
关于antd tree 和父子组件之间的传值问题(react 总结)
Jun 02 Javascript
js中scrollHeight,scrollWidth,scrollLeft,scrolltop等差别介绍
May 16 #Javascript
JS字符串累加Array不一定比字符串累加快(根据电脑配置)
May 14 #Javascript
JQuery 返回布尔值Is()条件判断方法代码
May 14 #Javascript
JQuery选择器特辑 详细小结
May 14 #Javascript
IE6背景图片不缓存问题解决方案及图片使用策略多个方法小结
May 14 #Javascript
js split 的用法和定义 js split分割字符串成数组的实例代码
May 13 #Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
May 11 #Javascript
You might like
加强版phplib的DB类
2008/03/31 PHP
Laravel使用消息队列需要注意的一些问题
2017/12/13 PHP
php微信公众号开发之翻页查询
2018/10/20 PHP
JavaScript窗口功能指南之在窗口中书写内容
2006/07/21 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
jquery插件开发之实现md5插件
2014/03/17 Javascript
AngularJS入门教程之Select(选择框)详解
2016/07/27 Javascript
输入法的回车与消息发送快捷键回车的冲突解决方法
2016/08/09 Javascript
前端设计师们最常用的JS代码汇总
2016/09/25 Javascript
12 款 JS 代码测试必备工具(翻译)
2016/12/13 Javascript
详解vue-cli快速构建项目以及引入bootstrap、jq
2017/05/26 Javascript
详解vue项目的构建,打包,发布全过程
2017/11/23 Javascript
通过 JS 判断页面是否有滚动条的实现方法
2018/04/05 Javascript
Vue2.4+新增属性.sync、$attrs、$listeners的具体使用
2020/03/08 Javascript
TypeScript的安装、使用、自动编译的实现
2020/04/10 Javascript
Python找出9个连续的空闲端口
2016/02/01 Python
pyenv命令管理多个Python版本
2017/03/26 Python
Python cookbook(数据结构与算法)保存最后N个元素的方法
2018/02/13 Python
python中plot实现即时数据动态显示方法
2018/06/22 Python
Python split() 函数拆分字符串将字符串转化为列的方法
2019/07/16 Python
django rest framework serializer返回时间自动格式化方法
2020/03/31 Python
使用pygame实现垃圾分类小游戏功能(已获校级二等奖)
2020/07/23 Python
Python基于staticmethod装饰器标示静态方法
2020/10/17 Python
HTML5+Canvas+CSS3实现齐天大圣孙悟空腾云驾雾效果
2016/04/26 HTML / CSS
GLAMGLOW格莱魅美国官网:美国知名的面膜品牌
2016/12/31 全球购物
职业生涯规划怎么写
2013/12/29 职场文书
《故都的秋》教学反思
2014/04/15 职场文书
三问三解心得体会
2014/09/05 职场文书
街道党工委党的群众路线教育实践活动对照检查材料思想汇报
2014/10/05 职场文书
财务助理岗位职责范本
2014/10/09 职场文书
2014年销售经理工作总结
2014/12/01 职场文书
2015年试用期工作总结
2014/12/12 职场文书
学校隐患排查制度
2015/08/05 职场文书
化验室安全管理制度
2015/08/06 职场文书
2016年优秀少先队辅导员事迹材料
2016/02/26 职场文书
Windows7下FTP搭建图文教程
2022/08/05 Servers