JavaScript 的性能优化:加载和执行(以及动态引入的外部 JS 文件在各浏览器中的加载顺序不一致)...

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一、JavaScript 的性能优化:加载和执行

随着 Web2.0 技术的不断推广,越来越多的应用使用 JavaScript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题。而这个问题又因 JavaScript 的阻塞特性变的复杂,也就是说当浏览器在执行 JavaScript 代码时,不能同时做其他任何事情。本文详细介绍了如何正确的加载和执行 JavaScript 代码,从而提高其在浏览器中的性能。

概览

无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。一个典型的例子就是在页面中使用document.write()。例如清单 1

清单 1 JavaScript 代码内嵌示例



    Source Example


    

当浏览器遇到

Hello world!

然而这种常规的做法却隐藏着严重的性能问题。在清单 2 的示例中,当浏览器解析到 

这段代码展示了在 HTML 文档中放置

带有 defer 属性的

这段代码在页面处理过程中弹出三次对话框。不支持 defer 属性的浏览器的弹出顺序是:“defer”、“script”、“load”。而在支持 defer 属性的浏览器上,弹出的顺序则是:“script”、“defer”、“load”。请注意,带有 defer 属性的

代码首先创建 SCRIPT 标记并插入到 HEAD 标记中,再将 SCRIPT 的 src 属性指向外部 JS 文件,由之后的 SCRIPT 标记中代码调用外部程序全局变量。

各浏览器表现及分析如下:

IE Firefox Opera 弹出($)函数体。此方法中动态附加进文档的 js 文件会阻断下一个 SCRIPT 标记内的代码解析,直至它全部解析完。
Chrome Safari 脚本出错,"$ is not defined"。此方法中动态附加进文档的 js 文件不会阻断下一个 SCRIPT 标记内的代码解析。

 

情况2:



代码首先创建 SCRIPT 标记,将 src 属性指向外部 JS 文件。最后插入到 HEAD 标记中,由之后的 SCRIPT 标记中代码调用外部程序全局变量。

各浏览器表现及分析如下:

Firefox Opera 弹出($)函数体。此方法中动态附加进文档的 js 文件会阻断下一个 SCRIPT 标记内的代码解析,直至它全部解析完。
IE Chrome Safari 脚本出错,"$ is not defined"。此方法中动态附加进文档的 js 文件不会阻断下一个 SCRIPT 标记内的代码解析。

情况3:

代码首先创建 SCRIPT 标记,将 src 属性指向外部 JS 文件。最后插入到 HEAD 标记中,其后代码立即调用外部程序全局变量。

各浏览器表现及分析如下:

所有浏览器 脚本出错,"$ is not defined"。此方法中动态附加进文档的 js 文件不会阻断同一个 SCRIPT 标记内的代码解析。

情况4:



代码获取某个 SCRIPT 标记的引用,在将其 src 属性指向外部 JS 文件,其后代码立即调用外部程序全局变量。

各浏览器表现及分析如下:

所有浏览器 脚本出错,"$ is not defined"。此方法中动态附加进文档的 js 文件不会阻断同一个 SCRIPT 标记内的代码解析。

情况5:





代码获取某个 SCRIPT 标记的引用,在将其 src 属性值变更为外部 JS 文件,由之后的 SCRIPT 标记中代码调用外部程序全局变量。

各浏览器表现及分析如下:

IE Firefox Opera 弹出($)函数体。此方法中动态附加进文档的 js 文件会阻断下一个 SCRIPT 标记内的代码解析,直至它全部解析完。
Chrome Safari 脚本出错,"$ is not defined"。此方法中动态附加进文档的 js 文件不会阻断下一个 SCRIPT 标记内的代码解析。

 

综合以上情况,对于动态插入的 SCRIPT 文件,使用不同的插入方法将有不同的表现,不能保证在各浏览器能阻塞其后脚本的执行。

解决方案

对于必须动态附加到文档的外部 js 文件,要保证动态引入的脚本全部执行完成后,才能执行后续代码。

可以将此部分代码封装后调用,如:

function loadScript(url, callback){
    var script = document.createElement ("script")
    script.type = "text/javascript";
    if (script.readyState){ //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" || script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);

参考链接

http://www.w3help.org/zh-cn/causes/BX9013#

http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/

转载于:https://my.oschina.net/tianshuo/blog/749008

你可能感兴趣的:(javascript,python,ViewUI)