《高性能javascript》读书笔记:第一章 加载和执行

因为:在一个html页面中,当有<script>标签时,无论是内嵌的还是外链的,都会阻塞页面的下载和渲染。

所以:尽量将<script>标签放到<body>标签的底部。

 

因为:每一个<script>标签初始化下载时都会阻塞页面渲染, 并且每一个<script>下载完后的执行也需要一定的延时。不仅仅是外链脚本,内嵌脚本也一样。

        并且多个外链脚本会增加http请求数量影响性能。 

所以: 尽量减少<script>的个数

 

因为:把一段内嵌脚本放在引用外链样式表<link>标签之后会导致页面阻塞去等待样式表的下载,这样做是为了确保内嵌脚本在执行时能获得最精确的样式信息。

所以:永远不要把内嵌脚本紧跟在<link>标签后面

 

多个外链的脚本应该通过离线打包工具或类似Yahoo!combo handler的实时的在线服务来实现。 

 

无阻塞脚本的秘诀在于,在页面加载完成后才加载javascript代码。也就是说在windows对象的load事件触发后再下载脚本。几种方式:

1,用扩展属性:defer

defer指明了脚本不会修改dom,因此代码能安全地延迟执行,下载和执行都不会阻塞页面渲染。

 示例:

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

     或 

<script defer>
            alert("晚于没有defer标记的脚本执行,早于window.onload执行"); 

        </script>  

缺点:只有IE4+和Firefox3.5+支持 

2,动态脚本元素:通过DOM(文档对象模型) 可以用javascript动态创建包括<script>标签在内的所有元素。

示例:

   var script=document.createElement("script");

     script.type="text/javascript";
    script.src="file1.js";
    document.getElementByTagName("head")[0].appendChild(script);//此处是加到head

使用此种方式下载文件时,返回的代码会立即执行(firefox和opera会等待此前所有动态脚本节点执行完毕)。 

firefox,opera,chrome和safari3以上版本会在<script>元素接收完成时触发一个load事件:

示例:      script.onload=function(){alert("接收完成");}; 

IE会触发一个readystatechange事件,<script>元素提供readystate属性(uninitialized:初始状态 ,loading:开始下载,loaded:下载完成,interactive:数据完成下载但尚不可用,complete:所有数据已准备就续)

示例:     

        script.onreadystatechange=function(){

        if(script.readystate="loaded"||script.readystate=="complete"){ //一般只要判断这两种情况
                    script.onreadystatechange=null;  //这里必须删除事件,以确保事件不会处理两次
                    alert("接收完成");  
                   }
        };

 这里提供一个供标准及IE共用的方法

 

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{//其它浏览器
        script.onload=function(){
            callback();
            };
        }
        script.src=url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

使用时直接调用就可以了

 

loadScript("file1.js",function(){
    alert("加载完成");
    });

 

或者串联起来按顺序下载多个

 

 loadScript("file1.js",function(){
     loadScript("file2.js",function(){
        alert("加载完成");
        });
    });

 

 3,XMLHttpRequest脚本注入:发送一个get请求,然后把获取到的响应作为script的内容,再用DOM加到head中。

这个的缺点是不能请求跨域的js文件,所以通常不用它。

4,推荐的无阻塞模式

   A,用上面所述的动态loadScript方法加载界面渲染必须的脚本,在加载完成的事件里再加载其它脚本,并且放在</body>闭合标签之前。建议用YUI Compressor把脚本进行压缩。

 B,LazyLoad类库 http://github.com/rgrove/lazyload       1.5K

示例:

<script type="text/javascript" src="lazyload-min.js"></script>
    <script type="text/javascript">
        LazyLoad.js(["file1.js","file2.js"],function(){ //如果只加载一个文件的话不需要中括号
            Application.init();
        });

</script>   

    

C,LABjs类库 http://labjs.com

示例:

<script type="text/javascript" src="lab.js"></script>
    <script type="text/javascript">
        $LAB.script("file1.js").wait()  //用这个wait能保证先执行完再下载file2.js。下面的file2.js和file3.js不一定谁先下载
            .script("file2.js")
            .script("file3.js")
            .wait(function(){ 
                Application.init();
            });

    </script>   


     

 

 

posted on 2012-01-07 23:20  LCM  阅读(1040)  评论(0编辑  收藏  举报

导航