Javascript性能优化(一) - 基本性能优化

目录

加载和执行

当浏览器解析到JS代码时,无论是内嵌代码还是外链文件,网页都会停下来等待代码的下载和执行(阻塞)。

能用GET请求尽量别用POST

Post请求会先发一个header再发数据,即会请求服务器两次,而GET请求只需要一个TCP报文就能完成。

多使用外部JS和CSS文件

原因很简单,因为浏览器会对文件缓存,当不同页面调用相同文件时文件会被重复使用。

精简JS和CSS文件

如果你阅读过JS第三方库的文件,会发现很多库文件代码都是集中在一行的,为什么?因为代码中的空格、空行、回车、注释会占用一笔占比不小的空间,所以当你发布项目的时候最好使用相关工具对文件进行打包精简,提高文件下载速度。

减少DOM访问

JS访问DOM元素没有我们想象的那么快,元素越多访问速度越慢,一个比较直观的解决方案是用一个局部变量来缓存已经访问过的元素。(具体原因会在下一篇中详细介绍)

使用智能事件处理

这里所说的智能事件处理需要开发者对事件处理有更加深入的了解,因为事件句柄会消耗大量性能,所以需要尽量少地触发事件,如一个DIV中有十个按钮需要事件句柄,那么我们可以将事件句柄放到DIV上,在事件冒泡过程中捕获该事件后再判断事件来源,这可能会增加事件句柄的复杂性,但是一定会提升总体性能。

脚本位置

  • 很多人喜欢把外链脚本放在head标签内,因为那样更加美观方便。但是当浏览器解析到外链脚本时,会停下来下载脚本执行脚本再继续向后解析,也就是说会导致页面阻塞,在脚本执行完毕之前页面将是一片空白。
  • 另外,脚本的下载和执行也不是并行的,如引入了1.js和2.js,那么整个过程将会是:下载1.js -> 执行1.js -> 下载2.js -> 执行2.js,显然效率很差。虽然IE8、Firefox2.5、Safari4和Chrome2开始允许脚本的并行下载,但是遗憾的是后续资源(样式、图片)的加载仍然需要等待脚本的下载和执行完毕。
  • 结论:脚本推荐放在末尾,让页面先显示出来,让页面加载看起来没有那么慢。

组织脚本

  • 因为页面每次遇到<script>标签都会停下来解析执行,所以应该尽可能减少<script>标签的数量
  • HTTP请求存在一定的开销,100K的文件比5个20K的文件下载的更快,所以较少脚本数量也是很有必要的
  • 当依赖的JS文件太多时,可以用一些打包工具进行打包
  • 内嵌脚本如果紧跟外链样式表后面会导致页面阻塞去等待样式表的下载,这样做是为了保证JS获取到最精确的样式信息,而如果HTML放在外链样式表和内嵌脚本之间是无阻塞加载的,所以建议内嵌脚本不要紧跟<link>标签

无阻塞脚本

之前所说的通过合并文件限制HTTP请求在大型网站面前效果就比较差了,当下载一个较大的脚本时会阻塞浏览器一段较长的事件,解决方案一个是在onload之后下载脚本,还有就是异步下载脚本。

  • 延迟加载脚本
// HTML4中可以使用defer属性来延迟加载脚本
// defer的脚本会在页面加载完成之后window.onload事件触发之前执行
// 局限性:只被 IE 4 和 Firefox 3.5 更高版本的浏览器所支持
<script type="text/javascript" src="script1.js" defer></script>

// HTML5定义了一个新的拓展属性:async
// 它的作用和defer一样,能够异步地加载和执行脚本
// 缺点:async下,只要脚本下载好就执行,不是按照原本的顺序来执行的
  • 动态脚本元素,这个最常用也是最有效的
// 通过JS创建script标签,这样里面脚本的加载和执行就会变成异步的 
// 问题:脚本下载完后就马上执行,可能会依赖顺序问题,如B用到了A中函数,但是B先下载完了
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "script1.js";
document.getElementByTagName("head")[0].appendChild(script);

// 解决这个依赖问题- Firefox、Opera, Chorme 和 Safari 3+
// script有一个onload事件,表示加载完毕
script.onload = function(){
    alert("Script loaded!");
}

// IE总是喜欢特例独行,你懂得,每个script标签都有一个状态,通过检测状态来判断执行情况 
script.onreadystatechange = function(){
    //因为loaded和complete都有几率出现,并不是唯一的
    if(script.readyState == "loaded" || script.readyState == "complete"){
        script.onreadystatechange = null //避免事件重复处理
        alert("Script loaded.");
    }
}

// 我们来把它封装一下,让他变得通用,而不再受限浏览器 
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.getElementByTagName("head")[0].appendChild(script);
}

//使用它
loadScript("script1.js",function(){
   alert("File is loaded"); 
});

//保证依赖顺序
loadScript("script1.js",function(){
    loadScript("script2.js",function(){
        loadScript("script3.js",function(){
            alert("All files are loaded!");
        });
    });
});

总结

减少 JavaScript 对性能的影响有以下几种方法:
- 将所有的<script>标签放到页面底部,也就是</body>闭合标签之前,这能确保在脚本执行前页面已经完成了渲染。
- 尽可能地合并脚本。页面中的<script>标签越少,加载也就越快,响应也越迅速。无论是外链脚本还是内嵌脚本都是如此。
- 采用无阻塞下载 JavaScript 脚本的方法:

使用<script>标签的 defer 属性(仅适用于 IE 和 Firefox 3.5 以上版本);
使用动态创建的<script>元素来下载并执行代码;
使用 XHR 对象下载 JavaScript 代码并注入页面中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值