本章我们讨论javascript在浏览器中是如果工作的,包括:下载、解析、执行的全过程。javascript的这些讨人嫌的地方我们是知道的:

i.需要串行下载

ii.需要解析

iii.需要串行执行

而在chrchromium中,js是这样解析的:(其实第一章末尾已经有了)

至于一些步骤的解释,这里就不再复述了,不懂的请戳:浏览器渲染过程 拉至末尾。

简直就是大魔王有木有?心中可有一万只草泥马奔腾而过?为什么在所有的下载线程中:

i.css加载不会阻塞页面

ii.images加载不会阻塞页面

iii.flash加载不会阻塞页面

iiii.activeX加载不会阻塞页面

iiiii.ajax还有同步异步之分

特么javascript文件就会阻塞页面!!

既然如此,我们能回避UI阻塞吗

i.在页面底部(</body>之前)引入js脚本,原因:由于js加载阻塞页面,而HTML是下载多少渲染多少,因此我们把它至于页面底部,让UI线程先执行完再加载js脚本

ii.根据具体情况,通过combo和compress减少请求数(通常在正式生产环境,我们将多个js脚本压缩为一个)

BUT ,这并没有真正回避UI阻塞,在</body>之前存在一个较大的脚本需要加载执行时,UI在ready后,需要较长的时间等待脚本加载和执行,在脚本ready前,UI是处于无事件响应状态的。

iii.defer属性

HTML4标准中为<script>标签定义的属性,用于告诉浏览器:内容中包含document.write之类破坏DOM的脚本

浏览器会无阻塞式(延迟)加载脚本,并且按页面中<script>标签顺序串行执行js脚本

在HTML渲染完毕之后,onload触发之前执行

支持:IE4.0+ ,FF3.5+

iiii.async属性

HTML5标准中为<script>标签定义的属性

对比defer,以下相同:

 无阻塞式加载

以下不同:

 加载完立即执行

不保证按照页面中<script>标签顺序执行

支持:FF3.6+ ,Chrome ,Opera10.5+ ,Safari ,IE9+

iiiii.不依赖浏览器版本的方式

Dynamic Script DOM ,比如google分析:

XHR Inject

XHR Eval

Script in Iframe

还有问题吗?当然还有:

i.并行、异步加载脚本也需要保证顺序、同源策略、CDN、缓存等因素的影响

ii.没有通用的解决方案,不过我们可以:

使用LABjs || requireJS || seaJS 等管理我们的脚本加载

服务端combo脚本

iii.以上可以相对完美的解决脚本下载问题,但这并不能解决脚本执行阻塞的问题

异步大法好

关于异步

i.你是否认为: 异步 == (方法 + 回调) ? 呵呵 ... 你懂得! 冒泡排序的异步例子:

var innerLoop = function (array, x, y, callback) {
 if (y < array.length - x) {
  compare(array[y], array[y + 1], function (r) {
   if (r > 0) {
    swap(array, y, y + 1, function () {
     innerLoop(array, x, y + 1, callback);
    });
   } else {
    innerLoop(array, x, y + 1, callback);
   }
  });
 } else {
  callback();
 }
} outerLoop(array, 0, function () {
 console.log("done!");
}
);
var compare = function (x, y, callback) {
 setTimeout(10, function () {
  callback(x - y);
 });
} var swap = function (a, i, j, callback) {
 var t = a[i]; a[i] = a[j]; a[j] = t;
 repaint(a);  setTimeout(20, callback);
} var outerLoop = function (array, x, callback) {
 if (x < array) {
  innerLoop(array, x, 0, function () {
   outerLoop(array, x + 1, callback);
  });
 } else {
 callback();
 }
}

ii.你是否认为: 浏览器是单线程执行的 ?

iii.你是否使用 setTimeout || setInterval 模拟过多线程 ?

iiii.异步编程是有难度的:

破坏了代码的局部性

难以应用于需要保持顺序的场景

难以处理异常及取消

难以操作异步之间的协作及组合

问题根源:

i.javascript是单线程语言

不能创建线程

不能开展并行任务

不能对线程操作

ii.阻塞UI渲染

如何解决:

i.浏览器并不是单线程的货,我们可以利用如下异步线程:

资源下载线程(javacript、images、css、object)

ajax线程

web worker线程

setTimeout模拟多线程

总结

我们可以使用各种组合方式、现代浏览器的新特性去处理这些问题,总而言之,没有一种方案是通用的。我们需要在对应的场景中找出最合适的方案,而这些方案无非是围绕这些原理做出的变体。

浏览器中JavaScript执行原理的更多相关文章

  1. 浏览器中Javascript单线程分析

    线程这个特性对于一门语言环境来说是尤其重要的,在Java/C++环境下都提供了多线程API操作. 但在Javascript中据说代码执行时单线程的,大量计算的逻辑会阻塞浏览器HTML渲染,但setTi ...

  2. 浏览器中js执行机制学习笔记

    浏览器中js执行机制学习笔记 RiverSouthMan关注 0.0772019.05.15 20:56:37字数 872阅读 291 同步任务 当一个脚本第一次执行的时候,js引擎会解析这段代码,并 ...

  3. 浏览器中Javascript的加载和执行

    在刚学习Javascript时曾对该问题在小组内做个一次StudyReport,发现其中的基础还是值得分析的. 从标题分析,可以加个Javascript的加载和执行分为两个阶段:加载.执行.而加载即浏 ...

  4. 浏览器中“JavaScript解析器”工作原理

    浏览器在读取HTML文件的时候,只有当遇到<script>标签的时候,才会唤醒所谓的“JavaScript解析器”开始工作. JavaScript解析器工作步骤: 1.“找一些东西”: v ...

  5. web浏览器中javascript

    1.异步载入一个js代码function loadasync(url) { var head = document.getElementsByTagName("head")[0]; ...

  6. javascript执行原理

    执行环境 当执行流执行到函数时会创建一个执行环境,这个执行环境包含了函数内部 语句可以访问的所有变量和函数,当代码执行完时,销毁执行环境.所以一般情 况下,局部变量在函数执行完时会被销毁. 作用域.调 ...

  7. 浏览器解析JavaScript的原理

    JavaScript的特点一般都知道的就是解释执行,逐行执行,就是从上到下依次执行. JavaScript的执行之前,其实还是有一些操作的,只是没有表现出来 JavaScript的执行过程: 1.语法 ...

  8. elasticsearch中filter执行原理深度剖析(bitset机制与caching机制)

    (1)在倒排索引中查找搜索串,获取document list date来举例 word doc1 doc2 doc3 2017-01-01 * *2017-02-02  *   *2017-03-03 ...

  9. JavaScript执行顺序分析

    之前从JavaScript引擎的解析机制来探索JavaScript的工作原理,下面我们以更形象的示例来说明JavaScript代码在页面中的执行顺序.如果说,JavaScript引擎的工作机制比较深奥 ...

随机推荐

  1. typedef 类型重命名 和 #define 宏定义(1)

    http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html 在现实生活中,信息的概念可能是长度,数量和面积等.在C语 ...

  2. 2016022611 - redis订阅发布命令集合

    redis消息订阅发布命令 参考地址:http://www.yiibai.com/redis/redis_pub_sub.html 消息发送者发送消息,通过redis的channal,消息接收者获取消 ...

  3. Action类一般情况为何要继承ActionSupport

    struts2中的action可以继承ActionSupport,也可以不继承ActionSupport.不继承ActionSupport的情况只需要有一个方法,返回String,即可,记住,在继承A ...

  4. 40个Android问题

    1. Android的四大组件是哪些,它们的作用? 答:Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持 ...

  5. Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  6. 【poi】解决java导出excel 海量数据内存溢出问题

    转自百度经验:http://jingyan.baidu.com/article/4853e1e5202c331909f72627.html 那里排版忒恶心,转来这里. 由于项目中有导出海量数据的需求, ...

  7. MySQL FEDERATED引擎使用示例, 类似Oracle DBLINK

    原文地址:http://it.dataguru.cn/article-3352-1.html 摘要: 本地MySQL数据库要访问远程MySQL数据库的表中的数据, 必须通过FEDERATED存储引擎来 ...

  8. 三大框架SSH(struts2+spring+hibernate)整合时相关配置文件的模板

    最近在学SSH三大框架的整合,在此对他们整合时相关配置文件做一简单的模板总结,方便以后复用! 首先是web.xml配置文件,这里面就配置一些简单的监听器.过滤器,包括spring核心配置文件appli ...

  9. 在Win32程序中显示Dos调试窗口,可暂停(AllocConsole,WriteConsole,FreeConsole函数,GetStdHandle函数取得输入句柄)

    在很多程序中,都可以看到程序运行中,会有一个Dos窗口,实时显示一些运行信息,这里就告诉大家是如何实现的,我们做个简单的,其实对控制台的操作还有很多,有兴趣的可以去查资料. 用到的API函数如下: / ...

  10. HTTP之Content-Length

    在HTTP协议中,有Content-Length的详细解读.Content-Length用于描述HTTP消息实体的传输长度the transfer-length of the message-body ...