游览器中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 相关文章推荐
通过js动态操作table(新增,删除相关列信息)
May 23 Javascript
[将免费进行到底]在Amazon的一年免费服务器上安装Node.JS, NPM和OurJS博客
Aug 18 Javascript
JavaScript入门系列之知识点总结
Mar 24 Javascript
使用Angular.js实现简单的购物车功能
Nov 21 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
Apr 07 Javascript
Vue2单一事件管理组件通信
May 09 Javascript
JS简单生成随机数(随机密码)的方法
May 11 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
Aug 27 Javascript
详解ES6 系列之异步处理实战
Oct 26 Javascript
vue-cli3 DllPlugin 提取公用库的方法
Apr 24 Javascript
基于vue和bootstrap实现简单留言板功能
May 30 Javascript
Javascript的promise,async和await的区别详解
Mar 24 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
安健A254立体声随身听的分析与打磨
2021/03/02 无线电
php empty函数 使用说明
2009/08/10 PHP
基于Windows下Apache PHP5.3.1安装教程
2010/01/08 PHP
php异常处理技术,顶级异常处理器
2012/06/13 PHP
关于PHP结束标签的使用细节探讨及联想
2013/03/04 PHP
php获取网页请求状态程序示例
2014/06/17 PHP
php导入大量数据到mysql性能优化技巧
2014/12/29 PHP
Laravel网站打开速度优化的方法汇总
2017/07/16 PHP
PHP实现的链式队列结构示例
2017/09/15 PHP
js中判断数字\字母\中文的正则表达式 (实例)
2012/06/29 Javascript
js截取固定长度的中英文字符的简单实例
2013/11/22 Javascript
jQuery实现自动切换播放的经典滑动门效果
2015/09/12 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
2017/03/09 Javascript
js实现图片加载淡入淡出效果
2017/04/07 Javascript
微信小程序自定义导航隐藏和显示功能
2017/06/13 Javascript
AngularJS 打开新的标签页实现代码
2017/09/07 Javascript
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
2017/10/15 Javascript
Angular2实现组件交互的方法分析
2017/12/19 Javascript
jQuery实现页码跳转式动态数据分页
2017/12/31 jQuery
Vue中 v-if 和v-else-if页面加载出现闪现的问题及解决方法
2018/10/12 Javascript
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
2018/11/14 Javascript
基于elementUI实现图片预览组件的示例代码
2019/03/31 Javascript
Python彩色化Linux的命令行终端界面的代码实例分享
2016/07/02 Python
Pandas中把dataframe转成array的方法
2018/04/13 Python
Python之pandas读写文件乱码的解决方法
2018/04/20 Python
Python基于property实现类的特性操作示例
2018/06/15 Python
python实现时间o(1)的最小栈的实例代码
2018/07/23 Python
如何解决python多种版本冲突问题
2020/10/13 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
2020/10/26 Python
用CSS3和table标签实现一个圆形轨迹的动画的示例代码
2019/01/17 HTML / CSS
PHP开发工程师面试问题集锦
2012/11/01 面试题
会计实习自我鉴定
2013/12/04 职场文书
2014年优秀党员材料
2014/12/18 职场文书
2015年安全生产月活动总结
2015/03/26 职场文书
实习证明格式范文
2015/06/16 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书