zoukankan      html  css  js  c++  java
  • JavaScript加载与执行

        多数情况下,浏览器是用单一进程处理用户界面和JavaScript脚本执行。所以,JavaScript的处理时间越久,浏览器等待响应事件就越长。

        简单地说,就是浏览器每次处理<script>标签,就会让页面等待脚本的解析和执行。这个过程页面渲染和用户交互是完全阻塞的。

    一、脚本位置

            H4规范指出,<script>标签可以放在<head>和<body>标签内,并允许出现多次。

        1.1 将脚本放在底部

                正常情况下,多个脚本放到<head>内,浏览器会一个一个脚本加载与执行,如果这个过程耗时过长,通常就会显示空白页面。

                IE8,Firefox3.5、Safari4和Chrome2都允许并行下载JavaScript脚本。所以,当加载一个<script>标签时,不会阻塞其他<script>标签,但是会阻塞其他资源的下载,比如图片等。

    二、组织脚本

            由于<script>标签初始下载都会阻塞页面渲染,所以减少<script>标签的数量会改善阻塞情况。这不仅仅包含外链脚本,也包含内嵌脚本。

        2.1 单个100k的文件将比4个25k的文件加载快

                考虑到HTTP请求会带来额外的性能开销,单个100k的文件将比4个25k的文件加载快。当依赖多个脚本文件时,尽量合并,用一个<script>标签引入。

        2.2 页面引入的脚本尽量是本网站的,而不是其他网站的。

                同样考虑HTTP请求的开销,请求本网站的脚本文件会比请求其他网站的脚本文件更快。

    三、无阻塞的脚本

        

        减小JavaScript文件大小和控制HTTP请求数

                JavaScript倾向于阻塞浏览器的某些处理过程,比如HTTP请求和页面的更新,这是最显著的影响性能的问题。因此,精简代码数量和HTTP请求数很必要。

        加载单个较大脚本文件会锁死浏览器一大段时间

                尽管下载单个较大脚本文件只产生一次HTTP请求,但是会锁死浏览器一大段时间。因此需要逐步加载JavaScript文件,这样做在某种程度上来说不会阻塞浏览器。

            总结的说:就是页面加载完后再加载JavaScript代码。

        3.1 延迟的脚本

            3.1.1 defer属性

                H4给<script>标签定义了一个扩展属性:defer。

                带有defer属性的<script>标签可以放到任意一个位置,因为,当解析到带defer的<script>标签时,只会下载脚本,而不会执行脚本,直到DOM加载完成。因为defer不会阻塞浏览器的其他进程,可以和其他资源并行下载。

                局限性:只有IE 4+ 和Firefox 3.5+的浏览器支持。

        3.2 动态脚本元素

            3.2.1 DOM创建<script>标签

                <script>标签和其他标签并无差异,可以DOM方法创建、移动、删除<script>元素。

                新创建的<script>标签如果下载JavaScript文件,无论何时下载都不会阻塞页面其他进程,放到<head>里都不会影响其他进程。

                通常,新创建的<script>标签放到<head>里比放到<body>里面更保险。因为<body>没完全加载完成时,IE浏览器可能抛出‘操作已中止’的异常。

            3.2.3 readystatechange事件

                IE支持另外一种实现方式,它会触发readystatechange事件。

                <script>元素提供一个readyState属性,它的值在外链文件下载过程的不同阶段会发生变化。

                该属性有五种取值:

                    初始状态:uninitialized  开始下载:loading  下载完成:loaded  数据完成下载但不能用:interactive  所以数据已准备就绪:complate

    var script = document.createElement("script");
    script.type = "text/javascript";
    
    // IE
    script.onreadystatechange = function () {
        if (script.readyState == "loaded" || script.readyState == "complate") {
            script.onreadystatechange = null;
            alert("Script loaded.");
        }
    }
    
    script.src = "file1.js";
    document.getElementsByTagName("head")[0].appendChild(script);

                上述代码这么做是因为在<script>的生命周期内,并非readyState的每个值都会被用到,这些值也不一定会被用到。最有用的两个值是loaded和complate。

                最靠谱的就是检测这两个状态,以确保事件不会处理两次。

        3.3 XMLHttpRequest脚本注入

               先创建XHR对象,再用它下载JavaScript文件,最后通过创建动态<script>元素将代码注入到页面中:

    var xhr = new XMLHttpRequest();
    xhr.open("get", "file1.js", true);
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4) {
            if (xhr.state >= 200 && xhr.state < 300 || xhr.state == 304){
                var script = document.screateElement("script");
                script.style = "text/javascript";
                script.text = xhr.responseText;
                document.body.appendChild(scripy);
            }
        }
    };
    xhr.send(null);

            这种方法的好处就是下载下来的脚本文件不会立即执行,另一优点就是它在所有主流浏览器中都可以正常工作。

            缺点是请求的脚本文件与页面要在同一个域内。因此大型的web应用不会用这种方法。

        3.4 推荐的无阻塞模式

            3.4.1 先加载页面初始化所必要的脚本代码,等页面初始化完成,再加载剩下的脚本代码。

    <script type="text/javascript" src="loader.js"></script>
    <script type="text/javascript">
        loadScript("the-rest.js", function(){
            Application.init();
        });
    </script>

                这样确保js执行过程不会阻塞页面其他内容的显示。第二个<script>执行时,DOM结构已经创建完毕,并做好了交互的准备。从而避免了需要另一个事件(比如windows.load)来检测页面是否准备好。

            3.4.2 将loadScript()函数直接嵌入到页面,避免多产生一次HTTP请求。

  • 相关阅读:
    归并排序
    [转]html5 Canvas画图教程(1)—画图的基本常识
    [转]浏览器工作原理
    [转]Web开发者和设计师必须要知道的 iOS 8 十个变化
    mobile web开发(1) html页面头部基本设置
    差点难产的HTML5
    感觉离开了好久
    Java----区别
    MySQL---sql语句优化
    MySQL---数据库优化
  • 原文地址:https://www.cnblogs.com/aaronthon/p/12218816.html
Copyright © 2011-2022 走看看