本章我们讨论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. iOS: plist实例

    // // main.m // OSXDemo0601_plist // // Created by yao_yu on 14-6-3. // Copyright (c) 2014年 yao_yu. ...

  2. mybaits不能出现小于号

    org.xml.sax.SAXParseException; lineNumber: 146; columnNumber: 54; The content of elements must consi ...

  3. WPF2D绘制图形方法

    我们先看看效果如何: xaml文件: <Window x:Class="WPF2D绘制图形方法.MainWindow" xmlns="http://schemas. ...

  4. uitableview的空白处不能响应 touchesbegan 事件

    现在的uitableview 的上面  响应不了     touchesbegan 事件   可能算是苹果的一个bug吧,不知道以后会不会改变 今天试了好久  都不行  最后  写了个字类  继承自 ...

  5. Java Fluent Restful API自动化测试框架

    这是一个Restful API自动化测试框架,这是一个能让你写出高可读性测试代码的测试框架! 项目目标 话说目前行业内,Restful API自动化测试框架已经不是稀罕物了,各个语言都有自己的实现机制 ...

  6. Java操作Oracle数据库以及调用存储过程

    操作Oracle数据库 publicclass DBConnection {     //jdbc:oracle:thin:@localhost:1521:orcl     publicstaticf ...

  7. 解决poi导出Excel异常org.openxmlformats.schemas.spreadshe

    JAVA报表 POI未捕获到 servlet OUTEXCEL 的其中一个服务方法中抛出的异常.抛出的异常:java.lang.NoClassDefFoundError: org.openxmlfor ...

  8. 你的 Docker 应用是安全的吗?

    近一年来,Docker 已经逐渐成为 container 界的事实标准,成为技术人员不可或缺的技能之一,就像 Docker 宣称的那样,「Build,Ship,and Run Any App,Anyw ...

  9. mysql主从配置(清晰的思路)

    mysql主从配置.鄙人是在如下环境测试的: 主数据库所在的操作系统:win7 主数据库的版本:5.0 主数据库的ip地址:192.168.1.111 从数据库所在的操作系统:linux 从数据的版本 ...

  10. DestroyWindow

    假设自己通过new创建了一个窗口对象pWnd,然后pWnd->Create.则销毁窗口的调用次序: 1.       手工调用pWnd->DestroyWindow(): 2.       ...