高性能javascript笔记:关于脚本的优化

脚本的阻塞特性:把脚本放在底部

<script>标签因脚本的加载,解析,运行而暂时整个页面的下载和解析过程。如果把它放在<head>标签里面。通常表现为:页面打开时,首先显示为一副空白的页面。

因为脚本阻塞其他页面资源的下载,所以推荐的方法就是:将所有的<script>标签放在尽可能接近<body>标签底部的位置即</body>之前。尽量减少对整个页面下载的影响。

减少脚本的数量

当页面解析每碰到一个<script>时,紧接着都会有一段时间用于js代码的运行,最小化这些延迟时间可以改善页面的性能。另外,对于外部js文件,会发出http请求,每个http请求都会产生额外的性能,下载一个100k的js文件要比下载4个25k的js文件要快,所以合并js有助于改善页面的性能。

精简js源代码及压缩脚本(gzip)

精简js源代码是指去除一个js文件中一切与运行无关的内容,包括注释和不必要的空格,使js源文件体积更小,下载更快。推荐使用JSMinDojo Compressor;压缩脚本需要在服务器做相应的配置,同样适用于样式表。

非阻塞加载脚本

非阻塞加载脚本是等页面加载完后再加载Javascript源码。从技术角度来说,这意味着在window的load事件发出后开始下载脚本。
延迟脚本:HTML4为<script>添加了一个defer属性,这个属性指明该脚本不会修改DOM,所以代码可以稍后执行。仅IE和FF3.5支持,其他浏览器依然阻塞。代码如下

<script type="text/javascript" src="file.js" defer="defer"></script>

任何支持带有defer属性的<script>元素在DOM加载完之前是不会被执行的,不管是内联脚本还是外部文件,所以它可以放到页面的任何位置。

动态添加脚本元素:<script>元素与其它元素一样,可以通过Javascript从文档中添加,移动,删除。代码如下

1 var script = document.createElement("script");
2 script.type = "text/javascript";
3 script.onload=function(){
4      //表示已经加载完
5 };
6 script.src = "file.js";
7 document.getElementsByTagName("head")[0].appendChild(script);

file.js文件当元素添加到页面后立刻开始下载,重点在于无论在何处启动下载,文件的下载和运行都不会阻塞其他页面资源的处理。因为可能要经常使用到,所以可以封装成一个跨浏览器的函数,方便以后使用:

 1 function asyncLoadScript(url,callback){
 2     var script = document.createElement("script");
 3     script.type = "text/javascript";
 4     if(script.readyState){//ie
 5         script.onreadystatechange = function(){
 6             if(script.readyState == "loaded" || script.readyState == "complete"){
 7                 script.onreadystatechange = null;
 8                 callback();
 9             }
10         }
11     }else{//other
12         script.onload = function(){
13             callback();
14         };
15     }
16     script.src = url;
17     document.body.appendChild(script);
18 }
19 //加载多个js,保证其顺序
20 asyncLoadScript("file1.js",function(){
21     asyncLoadScript("file2.js",function(){
22         asyncLoadScript("file3.js",function(){
23             //所有js加载完成
24         });        
25     });    
26 });

还有一种方法就是利用XMLHttpRequest对象异步加载js文件,此方法的优点是:在js文件加载完后才创建script元素,所以它下载后不会自动执行。缺点是js文件必须与页面放在同一个域内,不能从CDN(内容分发网络)下载,一般来说大型网站不会使用这种方法。代码如下:

 1 //跨浏览器创建XHR对象
 2 function createXHR(){
 3     if(typeof XMLHttpRequest != "undefined"){
 4         createXHR = function(){
 5             return new XMLHttpRequest();
 6         };
 7     }else if(typeof ActiveXObject != "undefined"){
 8         createXHR = function(){
 9             if(typeof arguments.callee.activeXString != "string"){
10                 var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
11                 for(var i=0; i<versions.length; i++){
12                     try{
13                         var xhr = new ActiveXObject(versions[i]);//试探浏览器支持能力
14                         arguments.callee.activeXString = versions[i];//把浏览器支持的XHR版本保存在activeXString属性中
15                         return xhr;
16                     }
17                     catch(ex){
18                         //skip
19                     }
20                 }    
21             }
22             return new ActiveXObject(arguments.callee.activeXString);
23         };
24     }else{
25         createXHR = function(){
26             throw new Error("No XMLHttpRequest object available.");
27         };
28     }
29     return createXHR();
30 }
31 //利用XHR对象异步加载JS
32 function XHRLoadScript(url,callback){
33     var xhr = createXHR();
34     //为保持跨浏览器兼容性,必须在调用open()之前指定onreadystatechange事件处理程序
35     xhr.onreadystatechange = function(){
36         if(xhr.readyState == 4){
37             if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
38                 var script = document.createElement("script");
39                 script.type = "text/javascript";
40                 script.text = xhr.responseText;
41                 document.body.appendChild(script);
42                 
43                 callback();
44             }
45         }
46     };
47     xhr.open("get",url,true);
48     //尽管不发送数据,但对于某些浏览器来说这个参数是必需的
49     xhr.send(null);
50     
51 }

使用其它库来加载js

1、Yahoo Search的lazyload      用法: LazyLoad.js([urlString|urlArray],function(){});
2、Kyle Simpson的LABjs         用法:$LAB.script(firstURL).script(secondURL).wait(function(){});

posted @ 2012-06-27 15:57  无赖君子  阅读(2173)  评论(4编辑  收藏  举报