zoukankan      html  css  js  c++  java
  • 浏览器中JavaScript执行原理

    本章我们讨论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模拟多线程

    总结

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

  • 相关阅读:
    [开源项目]蓝点无限TWR算法-多基站多标签固件
    [开源项目] 蓝点无限 UWB Python版本上位机
    记一次RabbitMQ的脑裂(网络分区)问题
    使用Docker持久化部署SQL Server
    .NET---Exceptionless 轻量级的分布式日志管理平台
    python性能测试工具locust
    Javascript —— 线转树 or 树转线
    记录一个生僻知识点 —— JS字符模板替换
    车证识别工具|行驶证识别工具|行驶证识别OCR工具免费版V3.0.0.0
    C# CAD 凹凸点识别最大轮廓
  • 原文地址:https://www.cnblogs.com/inJS/p/4912843.html
Copyright © 2011-2022 走看看