jQuery性能优化的38个建议


Posted in Javascript onMarch 04, 2014

一、注意定义jQuery变量的时候添加var关键字
这个不仅仅是jQuery,所有javascript开发过程中,都需要注意,请一定不要定义成如下:
$loading = $('#loading'); //这个是全局定义,不知道哪里位置倒霉引用了相同的变量名,就会郁闷至死的
二、请使用一个var来定义变量
如果你使用多个变量的话,请如下方式定义:

var page = 0,
   $loading = $('#loading'),
   $body = $('body');

不要给每一个变量都添加一个var关键字,除非你有严重的强迫症
三、定义jQuery变量是添加$符号
申明或者定义变量的时候,请记住如果你定义的是jQuery的变量,请添加一个$符号到变量前,如下:
var $loading = $('#loading');

这里定义成这样的好处在于,你可以有效的提示自己或者其它阅读你代码的用户,这是一个jQuery的变量。
四、DOM操作请务必记住缓存(cache)
在jQuery代码开发中,我们常常需要操作DOM,DOM操作是非常消耗资源的一个过程,而往往很多人都喜欢这样使用jQuery:
$('#loading').html('完毕');
$('#loading').fadeOut();

代码没有任何问题,你也可以正常运行出结果,但是这里注意你每次定义并且调用$('#loading')的时候,都实际创建了一个新的变量,如果你需要重用的话,记住一定要定义到一个变量里,这样可以有效的缓存变量内容,如下:
var $loading = $('#loading');
$loading.html('完毕');$loading.fadeOut();

这样性能会更好。
五、使用链式操作
上面那个例子,我们可以写的更简洁一些:
var $loading = $('#loading');
$loading.html('完毕').fadeOut();

六、精简jQuery代码
尽量把一些代码都整合到一起,请勿这样编码:
// !!反面人物
$button.click(function(){
    $target.css('width','50%');
    $target.css('border','1px solid #202020');
    $target.css('color','#fff');
});

应该这样书写:
$button.click(function(){
    $target.css({'width':'50%','border':'1px solid #202020','color':'#fff'});
});

七、避免使用全局类型的选择器
请勿如下方式书写:$('.something > *');
这样书写更好:$('.something').children();
八、不要叠加多个ID
请勿如下书写:$('#something #children');
这样就够了:$('#children');
九、多用逻辑判断||或者&&来提速
请勿如下书写:
if(!$something) {
    $something = $('#something ');
}

这样书写性能更好:
$something= $something|| $('#something');

十、尽量使用更少的代码
与其这样书写:if(string.length > 0){..}
不如这样书写:if(string.length){..}
十一、尽量使用.on方法
如果你使用比较新版本的jQuery类库的话,请使用.on,其它任何方法都是最终使用.on来实现的。
十二、尽量使用最新版本的jQuery
最新版本的jQuery拥有更好的性能,但是最新的版本可能不支持ie6/7/8,所以大家需要自己针对实际情况选择。
十三、尽量使用原生的Javascript
如果使用原生的Javascript也可以实现jQuery提供的功能的话,推荐使用原生的javascript来实现。
十四、总是从#id选择器来继承
这是jQuery选择器的一条黄金法则。jQuery选择一个元素最快的方法就是用ID来选择了。
$('#content').hide();

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

十五、在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'); // 非常慢,不要使用

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

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

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

十八、 采用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

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

二十、 缓存jQuery对象
将你经常用的元素缓存起来:
var header = $('#header');
var divs = header.find('div');
var forms = header.find('form');

当要进行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>');

}
二十二、 尽管jQuery不会抛出异常,但开发者也应该检查对象

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

App.hiddenDivs = $('div.hidden');
// 之后在你的应用中调用:
App.hiddenDivs.find('span');

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

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

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

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

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

三十一、jQuery单元测试
测试JavaSript代码最好的方法就是人来测试。但你可以使用一些自动化的工具如Selenium,Funcunit,QUit,QMock来测试你的代码(尤其是插件)。我想在另外一个专题来讨论这个话题因为实在有太多要说的了。
十二、 标准化你的jQuery代码
经常标准化你的代码,看看哪个查询比较慢,然后替换它。你可以用Firebug控制台。你也可以使用jQuery的快捷函数来使测试变得更容易些:
// 在Firebug控制台记录数据的快捷方式
$.l($('div'));
// 获取UNIX时间戳
$.time();
// 在Firebug记录执行代码时间
$.lt();
$('div');
$.lt();
// 将代码块放在一个for循环中测试执行时间
$.bm("var divs = $('.testdiv', '#pageBody');"); // 2353 on Firebug 3.6

三十三、使用HMTL5
新的HTML5标准带来的是更轻巧的DOM结构。更轻巧的结构意味着使用jQuery需要更少的遍历,以及更优良的载入性能。所以如果可能的话请使用HTML5。
三十四、如果给15个以上的元素加样式时,直接给DOM元素添加style标签
要给少数的元素加样式,最好的方法就是使用jQuey的css()函数。然而更15个以上的较多的元素添加样式时,直接给DOM添加style 标签更有效些。这个方法可以避免在代码中使用硬编码(hard code)。
$('<style type="text/css"> div.class { color: red; } </style>')
.appendTo('head');

三十五、避免载入多余的代码
将Javascript代码放在不同的文件中是个好的方法,仅在需要的时候载入它们。这样你不会载入不必要的代码和选择器。也便于管理代码。
三十六、压缩成一个主JS文件,将下载次数保持到最少
当你已经确定了哪些文件是应该被载入的,那么将它们打包成一个文件。用一些开源的工具可以自动帮你完成,如使用Minify(和你的后端代码集成)或者使用JSCompressor,YUI Compressor 或 Dean Edwards JS packer等在线工具可以为你压缩文件。我最喜欢的是JSCompressor。
三十七、需要的时候使用原生的Javasript
使用jQuery是个很棒的事情,但是不要忘了它也是Javascript的一个框架。所以你可以在jQuery代码有必要的时候也使用原生的Javascript函数,这样能获得更好的性能。
三十八、 缓慢载入内容不仅能提高载入速度,也能提高SEO优化 (Lazy load content for speed and SEO benefits)
使用Ajax来载入你的网站吧,这样可以节约服务器端载入时间。你可以从一个常见的侧边栏widget开始。
Javascript 相关文章推荐
file模式访问网页时iframe高度自适应解决方案
Jan 16 Javascript
JS getAttribute和setAttribute(取得和设置属性)的使用介绍
Jul 10 Javascript
js数组操作学习总结
Nov 04 Javascript
解决jquery无法找到其他父级子集问题的方法
May 10 Javascript
jquery div模态窗口的简单实例
May 28 Javascript
JS遍历页面所有对象属性及实现方法
Aug 01 Javascript
JavaScript中运算符规则和隐式类型转换示例详解
Sep 06 Javascript
vue 使用eventBus实现同级组件的通讯
Mar 02 Javascript
jQuery判断自定义属性data-val用法示例
Jan 07 jQuery
vue-cli 项目打包完成后运行文件路径报错问题
Jul 19 Javascript
解决layer 关闭当前弹窗 关闭遮罩层 input值获取不到的问题
Sep 25 Javascript
jquery实现购物车基本功能
Oct 25 jQuery
javascript设计模式之工厂模式示例讲解
Mar 04 #Javascript
js调用iframe实现打印页面内容的方法
Mar 04 #Javascript
JavaScript的21条基本知识点
Mar 04 #Javascript
js的2种继承方式详解
Mar 04 #Javascript
Seajs的学习笔记
Mar 04 #Javascript
文本域中换行符的替换示例
Mar 04 #Javascript
为jquery的ajaxfileupload增加附加参数的方法
Mar 04 #Javascript
You might like
神族 Protoss 历史背景
2020/03/14 星际争霸
php+mysql删除指定编号员工信息的方法
2015/01/14 PHP
CodeIgniter删除和设置Cookie的方法
2015/04/07 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
thinkphp诸多限制条件下如何getshell详解
2020/12/09 PHP
JavaScript入门教程(5) js Screen屏幕对象
2009/01/31 Javascript
jQuery的学习步骤
2011/02/23 Javascript
js正则表达式的使用详解
2013/07/09 Javascript
使用jQuery实现的掷色子游戏动画效果
2014/03/14 Javascript
JavaScript调用ajax获取文本文件内容实现代码
2014/03/28 Javascript
Extjs Label的 fieldLabel和html属性值对齐的方法
2014/06/15 Javascript
用javascript关闭本窗口技巧小结
2014/09/05 Javascript
jQuery带时间的日期控件代码分享
2015/08/26 Javascript
JavaScript设计模式开发中组合模式的使用教程
2016/05/18 Javascript
微信小程序实现图片轮播及文件上传
2017/04/07 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
详解React-Native全球化多语言切换工具库react-native-i18n
2017/11/03 Javascript
vue.js 实现点击按钮动态添加li的方法
2018/09/07 Javascript
微信小程序云开发 搭建一个管理小程序
2019/05/17 Javascript
使用layui定义一个模块并使用的例子
2019/09/14 Javascript
react实现同页面三级跳转路由布局
2019/09/26 Javascript
AutoJs实现刷宝短视频的思路详解
2020/05/22 Javascript
解决ant design vue中树形控件defaultExpandAll设置无效的问题
2020/10/26 Javascript
[04:16]DOTA2英雄梦之声_第09期_斧王
2014/06/21 DOTA
[00:37]DOTA2上海特级锦标赛 Secert 战队宣传片
2016/03/03 DOTA
跟老齐学Python之集成开发环境(IDE)
2014/09/12 Python
python处理RSTP视频流过程解析
2020/01/11 Python
python实现计算器简易版
2020/12/17 Python
python的scipy.stats模块中正态分布常用函数总结
2021/02/19 Python
百思买加拿大:Best Buy Canada
2018/03/20 全球购物
《海底世界》教学反思
2014/04/16 职场文书
2014年教务处工作总结
2014/12/03 职场文书
考研英语复习计划
2015/01/19 职场文书
公司承诺书格式范文
2015/04/28 职场文书
信访维稳承诺书
2015/05/04 职场文书
教师学习中国梦心得体会
2016/01/05 职场文书