jQuery性能优化28条建议你值得借鉴


Posted in Javascript onFebruary 16, 2013

jQuery性能优化28条建议 一直在寻找有关jQuery性能优化方面的小窍门,能让我那臃肿的动态网页应用变得轻便些。找了很多文章后,我决定将最好最常用的一些优化性能的建议列出来。我也做了一个jQuery性能优化的简明样式表,你可以打印出来或者设为桌面背景。
一、选择器性能优化建议
1. 总是从#id选择器来继承
这是jQuery选择器的一条黄金法则。jQuery选择一个元素最快的方法就是用ID来选择了。

$('#content').hide();

或者从ID选择器继承来选择多个元素:
$('#content p').hide();

2. 在class前面使用tag
jQuery中第二快的选择器就是tag选择器(如$(‘head')),因为它和直接来自于原生的Javascript方法getElementByTagName()。所以最好总是用tag来修饰class(并且不要忘了就近的ID)
var receiveNewsletter = $('#nslForm input.on');

jQuery中class选择器是最慢的,因为在IE浏览器下它会遍历所有的DOM节点。尽量避免使用class选择器。也不要用tag来修饰ID。下面的例子会遍历所有的div元素来查找id为'content'的那个节点:
var content = $('div#content'); // 非常慢,不要使用

用ID来修饰ID也是画蛇添足:
var traffic_light = $('#content #traffic_light'); // 非常慢,不要使用

3. 使用子查询
将父对象缓存起来以备将来的使用
var header = $('#header'); 
var menu = header.find('.menu'); 
// 或者 
var menu = $('.menu', header);

4. 优化选择器以适用Sizzle的“从右至左”模型
自版本1.3之后,jQuery采用了Sizzle库,与之前的版本在选择器引擎上的表现形式有很大的不同。它用“从左至右”的模型代替了“从右至左”的模型。确保最右的选择器具体些,而左边的选择器选择范围较宽泛些:
var linkContacts = $('.contact-links div.side-wrapper');

而不要使用
var linkContacts = $('a.contact-links .side-wrapper');

5. 采用find(),而不使用上下文查找
.find()函数的确快些。但是如果一个页面有许多DOM节点时,需要来回查找时,可能需要更多时间:
var divs = $('.testdiv', '#pageBody'); // 2353 on Firebug 3.6 
var divs = $('#pageBody').find('.testdiv'); // 2324 on Firebug 3.6 - The best time 
var divs = $('#pageBody .testdiv'); // 2469 on Firebug 3.6

6. 利用强大的链式操作
采用jQuery的链式操作比缓存选择器更有效:
$('li.menu-item').click(function () {alert('test click');}) 
.css('display', 'block') 
.css('color', 'red') 
fadeTo(2, 0.7);

7. 编写属于你的选择器
如果你经常在代码中使用选择器,那么扩展jQuery的$.expr[':']对象吧,编写你自己的选择器。下面的例子中,我创建了一个abovethefold选择器,用来选择不可见的元素:
$.extend($.expr[':'], { 
abovethefold: function(el) { 
return $(el).offset().top < $(window).scrollTop() + $(window).height(); 
} 
}); 
var nonVisibleElements = $('div:abovethefold'); // 选择元素

二、优化DOM操作建议
8. 缓存jQuery对象
将你经常用的元素缓存起来:
var header = $('#header'); 
var divs = header.find('div'); 
var forms = header.find('form');

9. 当要进行DOM插入时,将所有元素封装成一个元素
直接的DOM操作很慢。尽可能少的去更改HTML结构。
var menu = '<ul id="menu">'; 
for (var i = 1; i < 100; i++) { 
menu += '<li>' + i + '</li>'; 
} 
menu += '</ul>'; 
$('#header').prepend(menu); 
// 千万不要这样做: 
$('#header').prepend('<ul id="menu"></ul>'); 
for (var i = 1; i < 100; i++) { 
$('#menu').append('<li>' + i + '</li>'); 
}

10. 尽管jQuery不会抛出异常,但开发者也应该检查对象
尽管jQuery不会抛出大量的异常给用户,但是开发者也不要依赖于此。jQuery通常会执行了一大堆没用的函数之后才确定一个对象是否存在。所以在对一个作一系列引用之前,应先检查一下这个对象存不存在。
11. 使用直接函数,而不要使用与与之等同的函数
为了获得更好的性能,你应该使用直接函数如$.ajax(),而不要使用$.get(),$.getJSON(),$.post(),因为后面的几个将会调用$.ajax()。
12. 缓存jQuery结果,以备后来使用
你经常会获得一个javasript应用对象——你可以用App.来保存你经常选择的对象,以备将来使用:
App.hiddenDivs = $('div.hidden'); 
// 之后在你的应用中调用: 
App.hiddenDivs.find('span');

13. 采用jQuery的内部函数data()来存储状态
不要忘了采用.data()函数来存储信息:
$('#head').data('name', 'value'); 
// 之后在你的应用中调用: 
$('#head').data('name');

14. 使用jQuery utility函数
不要忘了简单实用的jQuery的utility函数。我最喜欢的是$.isFunction(), $isArray()和$.each()。
15. 为HTML块添加“JS”的class
当jQuery载入之后,首先给HTML添加一个叫”JS”的class
$('HTML').addClass('JS');

只有当用户启用JavaScript的时候,你才能添加CSS样式。例如:
/* 在css中 */ 
.JS #myDiv{display:none;}

所以当JavaScript启用的时候,你可以将整个HTML内容隐藏起来,用jQuery来实现你想实现的(譬如:收起某些面板或当用户点击它们时展开)。而当Javascript没有启用的时候,浏览器呈现所有的内容,搜索引擎爬虫也会勾去所有内容。我将来会更多的使用这个技巧。
三、关于优化事件性能的建议
16. 推迟到$(window).load
有时候采用$(window).load()比$(document).ready()更快,因为后者不等所有的DOM元素都下载完之前执行。你应该在使用它之前测试它。
17. 使用Event Delegation
当你在一个容器中有许多节点,你想对所有的节点都绑定一个事件,delegation很适合这样的应用场景。使用Delegation,我们仅需要在父级绑定事件,然后查看哪个子节点(目标节点)触发了事件。当你有一个很多数据的table的时候,你想对td节点设置事件,这就变得很方便。先获得table,然后为所有的td节点设置delegation事件:
$("table").delegate("td", "hover", function(){ 
$(this).toggleClass("hover"); 
});

18. 使用ready事件的简写
如果你想压缩js插件,节约每一个字节,你应该避免使用$(document).onready()
// 也不要使用 
$(document).ready(function (){ 
// 代码 
}); 
// 你可以如此简写: 
$(function (){ 
// 代码 
});

四、测试jQuery
19. jQuery单元测试
测试JavaSript代码最好的方法就是人来测试。但你可以使用一些自动化的工具如Selenium,Funcunit,QUit,QMock来测试你的代码(尤其是插件)。我想在另外一个专题来讨论这个话题因为实在有太多要说的了。
20. 标准化你的jQuery代码
经常标准化你的代码,看看哪个查询比较慢,然后替换它。你可以用Firebug控制台。你也可以使用jQuery的快捷函数来使测试变得更容易些:
// 在Firebug控制台记录数据的快捷方式 
$.l($('div'));

// 获取UNIX时间戳 
$.time();

// 在Firebug记录执行代码时间 
$.lt(); 
$('div'); 
$.lt();

// 将代码块放在一个for循环中测试执行时间 
$.bm("var divs = $('.testdiv', '#pageBody');"); // 2353 on Firebug 3.6

五、其他常用jQuery性能优化建议
21. 使用最新版本的jQuery
最新的版本往往是最好的。更换了版本后,不要忘记测试你的代码。有时候也不是完全向后兼容的。
22. 使用HMTL5
新的HTML5标准带来的是更轻巧的DOM结构。更轻巧的结构意味着使用jQuery需要更少的遍历,以及更优良的载入性能。所以如果可能的话请使用HTML5。
23. 如果给15个以上的元素加样式时,直接给DOM元素添加style标签
要给少数的元素加样式,最好的方法就是使用jQuey的css()函数。然而更15个以上的较多的元素添加样式时,直接给DOM添加style 标签更有效些。这个方法可以避免在代码中使用硬编码(hard code)。
$('<style type="text/css"> div.class { color: red; } </style>') 
.appendTo('head');

24. 避免载入多余的代码
将Javascript代码放在不同的文件中是个好的方法,仅在需要的时候载入它们。这样你不会载入不必要的代码和选择器。也便于管理代码。
25. 压缩成一个主JS文件,将下载次数保持到最少
当你已经确定了哪些文件是应该被载入的,那么将它们打包成一个文件。用一些开源的工具可以自动帮你完成,如使用Minify(和你的后端代码集成)或者使用JSCompressor,YUI Compressor 或 Dean Edwards JS packer等在线工具可以为你压缩文件。我最喜欢的是JSCompressor。
26. 需要的时候使用原生的Javasript
使用jQuery是个很棒的事情,但是不要忘了它也是Javascript的一个框架。所以你可以在jQuery代码有必要的时候也使用原生的Javascript函数,这样能获得更好的性能。
27. 从Google载入jQuery框架
当你的应用正式上线的时候,请从Google CDN载入jQuery,因为用户可以从最近的地方获取代码。这样你可以减少服务器请求,而用户如果浏览其他网站,而它也使用Google CDN的jQuery时,浏览器就会立即从缓存中调出jQuery代码。
// 链接特定版本的压缩代码 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>

28. 缓慢载入内容不仅能提高载入速度,也能提高SEO优化 (Lazy load content for speed and SEO benefits)
使用Ajax来载入你的网站吧,这样可以节约服务器端载入时间。你可以从一个常见的侧边栏widget开始。
Javascript 相关文章推荐
Javascript动态绑定事件的简单实现代码
Dec 25 Javascript
js中各浏览器中鼠标按键值的差异
Apr 07 Javascript
js获取图片大小的函数代码
Sep 20 Javascript
实用的JS正则表达式(手机号码/IP正则/邮编正则/电话等)
Jan 11 Javascript
jQuery取得iframe中元素的常用方法详解
Jan 14 Javascript
CSS+jQuery实现简单的折叠菜单
Dec 20 Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 Javascript
认识jQuery的Promise的具体使用方法
Oct 10 jQuery
JS实现的找零张数最小问题示例
Nov 28 Javascript
layui从数据库中获取复选框的值并默认选中方法
Aug 15 Javascript
详解JSON.stringify()的5个秘密特性
May 26 Javascript
react合成事件与原生事件的相关理解
May 13 Javascript
JavaScript调用堆栈及setTimeout使用方法深入剖析
Feb 16 #Javascript
js nextSibling属性和previousSibling属性概述及使用注意
Feb 16 #Javascript
jQuery事件绑定.on()简要概述及应用
Feb 07 #Javascript
10个基于浏览器的JavaScript调试工具分享
Feb 07 #Javascript
利用JQuery动画制作滑动菜单项效果实现步骤及代码
Feb 07 #Javascript
jquery 选择器引擎sizzle浅析
Feb 06 #Javascript
extjs3 combobox取value和text案例详解
Feb 06 #Javascript
You might like
Get或Post提交值的非法数据处理
2006/10/09 PHP
PHP数组交集的优化代码分析
2011/03/06 PHP
yii用户注册表单验证实例
2015/12/26 PHP
PHP读MYSQL中文乱码的快速解决方法
2016/10/01 PHP
js 绑定带参数的事件以及手动触发事件
2010/04/27 Javascript
JavaScript prototype属性使用说明
2010/05/13 Javascript
解决Extjs 4 Panel作为Window组件的子组件时出现双重边框问题
2013/01/11 Javascript
使用js如何实现全选与全不选
2013/12/30 Javascript
jQuery mobile类库使用时加载导航历史的方法简介
2015/12/04 Javascript
原生javascript实现自动更新的时间日期
2016/02/12 Javascript
Javascript的表单验证-初识正则表达式
2016/03/18 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
2016/04/01 Javascript
jquery拖动层效果插件用法实例分析(附demo源码)
2016/04/28 Javascript
全面解析Bootstrap中transition、affix的使用方法
2016/05/30 Javascript
url传递的参数值中包含&amp;时,url自动截断问题的解决方法
2016/08/02 Javascript
js仿支付宝多方框输入支付密码效果
2016/09/27 Javascript
浅谈js之字面量、对象字面量的访问、关键字in的用法
2016/11/20 Javascript
基于Node.js的WebSocket通信实现
2017/03/11 Javascript
layui框架中layer父子页面交互的方法分析
2017/11/15 Javascript
使用vue + less 实现简单换肤功能的示例
2018/02/21 Javascript
JS中promise化微信小程序api
2018/04/12 Javascript
vue导航栏部分的动态渲染实例
2019/11/01 Javascript
Vue使用轮询定时发送请求代码
2020/08/10 Javascript
在Python中移动目录结构的方法
2016/01/31 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
python自动循环定时开关机(非重启)测试
2019/08/26 Python
Python面向对象编程基础实例分析
2020/01/17 Python
python中的 zip函数详解及用法举例
2020/02/16 Python
如何学习Python time模块
2020/06/03 Python
python 如何调用远程接口
2020/09/11 Python
html5定位获取当前位置并在百度地图上显示
2014/08/22 HTML / CSS
英国女装网上商店:I Saw It First
2018/10/18 全球购物
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
一道写SQL的面试题和答案
2013/11/19 面试题
数据库什么时候应该被重组
2012/11/02 面试题
2019个人半年工作总结
2019/06/21 职场文书