jQuery代码性能优化的10种方法


Posted in Javascript onJune 21, 2016

1、总是使用#id去寻找element.

在jQuery中最快的选择器是ID选择器 ($('#someid')). 这是因为它直接映射为JavaScript的getElementById()方法。
选择单个元素

<div id="content">

 <form method="post" action="/">

  <h2>Traffic Light</h2>

  <ul id="traffic_light">

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

  </ul>

  <input class="button" id="traffic_button" type="submit" value="Go" />

 </form>

</div>

选择button的性能不好的一种方式:

var traffic_button = $('#content .button');

取而代之的是直接选择button:

var traffic_button = $('#traffic_button');

选择多个元素

在我们讨论选择多个元素的时候,我们真正需要知道的是DOM的遍历和循环才是性能低下的原因。为了尽量减少性能损失, 总是使用最近的父ID去寻找。

var traffic_lights = $('#traffic_light input');

2、在Classes前面使用Tags

在jQuery中第二快的选择器就是Tag选择器 ($('head')). 而这是因为它直接映射到JavaScript的getElementsByTagName()方法。

<div id="content">

 <form method="post" action="/">

  <h2>Traffic Light</h2>

  <ul id="traffic_light">

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

  </ul>

  <input class="button" id="traffic_button" type="submit" value="Go" />

 </form>

</div>

总是在一个Class前面加上一个tag名字(记得从一个ID传下来)

var active_light = $('#traffic_light input.on');

注意:在jQuery里Class选择器是最慢的一个选择器;在IE中它循环整个DOM。可能的话尽量避免使用它。不要在ID前面 加Tags。例如,它会因为去循环所有的<div>元素去寻找ID为content的<div>,而导致很慢。

var content = $('div#content');

按照同样的思路,从多个ID传下来是冗余的。

var traffic_light = $('#content #traffic_light');

3、缓存jQuery对象

养成保存jQuery对象到一个变量上(就像上面的例子)的习惯。例如,不要这样做:

$('#traffic_light input.on).bind('click', function(){...});

$('#traffic_light input.on).css('border', '3px dashed yellow');

$('#traffic_light input.on).css('background-color', 'orange');

$('#traffic_light input.on).fadeIn('slow');

取而代之,首现保存jQuery变量到一个本地变量后,再继续你的操作。

var $active_light = $('#traffic_light input.on');
 
$active_light.bind('click', function(){...});
 
$active_light.css('border', '3px dashed yellow');
 
$active_light.css('background-color', 'orange');
 
$active_light.fadeIn('slow');

提示:使用$前辍表示我们的本地变量是一个jQuery包集。记住,不要在你的应该程序里出现一次以上的jQuery重复的选择操作。 额外提示:延迟存储jQuery对象结果。

如果你想在你的程序的其它地方使用jQuery结果对象(result object(s)),或者你的函数要执行多次,要把它缓存在一个全局范围的对象里。通过定义一个全局容器保存jQuery结果对象,就可以在其它的函数里引用它。

// Define an object in the global scope (i.e. the window object)

window.$my ={

 // Initialize all the queries you want to use more than once

 head : $('head'),

 traffic_light : $('#traffic_light'),

 traffic_button : $('#traffic_button')};

function do_something(){

 // Now you can reference the stored results and manipulate them

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

 $my.head.append(script);

 // When working inside functions, continue to save jQuery results

 // to your global container.

 $my.cool_results = $('#some_ul li');

 $my.other_results = $('#some_table td');

 // Use the global functions as you would a normal jQuery result

 $my.other_results.css('border-color', 'red');

 $my.traffic_light.css('border-color', 'green');

}

4、更好的利用链

前面的例子也可以这样写:

var $active_light = $('#traffic_light input.on');

$active_light.bind('click', function(){...})

 .css('border', '3px dashed yellow')

 .css('background-color', 'orange')

 .fadeIn('slow');

这样可以让我们写更少的代码,使JavaScript更轻量。

5、使用子查询

jQuery允许我们在一个包集上附加其它的选择器。因为我们已经在本地变量里保存了父对象这样会减少以后在选择器上的性能开销。

<div id="content">

 <form method="post" action="/">

  <h2>Traffic Light</h2>

  <ul id="traffic_light">

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

  </ul>

  <input class="button" id="traffic_button" type="submit" value="Go" />

 </form>

</div>

例如,我们可以利用子查询缓存active和inactive lights以便后面的操作。

var $traffic_light = $('#traffic_light'), 

$active_light = $traffic_light.find('input.on'), 

$inactive_lights = $traffic_light.find('input.off');

提示:可以用逗号隔开一次定义多个本地变量,这样可以节省一些字节。

6、限制直接对DOM操作

DOM操作的基本做法是在内存中创建DOM结构,然后再更新DOM结构。这不是jQuery最好的做法,但对JavaScript来讲是高效的。直接操作DOM结构性能是低下的。 例如,如果你需要动态创建一列元素,不要这样做:

var top_100_list = [...], // assume this has 100 unique strings 

$mylist = $('#mylist'); // jQuery selects our <ul> element

for (var i=0, l=top_100_list.length; i<l; i++){ 

 $mylist.append('<li>' + top_100_list[i] + '</li>');

}

取而代之,我们希望在插入DOM结构之前先在一个字符串里创建一套元素。
代码

var top_100_list = [...], // assume this has 100 unique strings 

$mylist = $('#mylist'), // jQuery selects our <ul> element 

top_100_li = ""; // This will store our list items

for (var i=0, l=top_100_list.length; i<l; i++){

 top_100_li += '<li>' + top_100_list[i] + '</li>';

}

$mylist.html(top_100_li);

更快的做法,在插入DOM结构之前我们应该总是在一个父节点里包含许多元素

var top_100_list = [...], // assume this has 100 unique strings 

$mylist = $('#mylist'), // jQuery selects our <ul> element 

top_100_ul = '<ul id="#mylist">'; // This will store our entire unordered list

for (var i=0, l=top_100_list.length; i<l; i++){

 top_100_ul += '<li>' + top_100_list[i] + '</li>';

}

top_100_ul += '</ul>'; // Close our unordered list

$mylist.replaceWith(top_100_ul);

如是你照着上面的做了还是对性能有些迷惑的话,可以参考以下内容:

* 试一下jQuery提供的Clone()方法。Clone()方法创建节点数的拷贝,随后你可以在这个副本中进行操作。

* 使用DOM DocumentFragments. As the creator of jQuery points out, 比直接操作DOM性能上更好. 先创建你需要的结构(就像我们上面用一个字符串做的一样), 然后使用jQuery的 insert or replace methods.

7、事件委托(又名:冒泡事件)

除非特别说明,每一个JavaScript事件(如click, mouseover 等)在DOM结构树上都会冒泡到它的父元素上。如果我们想让很多elements(nodes)调用同一个function这是非常有用的。取而代之的是 你可以只对它们的父级绑定一次,而且可以计算出是哪一个节点触发了事件,而不是绑定一个事件监听器到很多节点上这种效率低下的方式。例如,假如我们要开发 一个包含很多input的大型form,当input被选择的时候我们想绑定一个class name。像这样的帮定是效率低下的:

$('#myList li).bind('click', function(){

 $(this).addClass('clicked'); // do stuff

});

反而,我们应该在父级侦听click事件。

$('#myList).bind('click', function(e){

 var target = e.target, // e.target grabs the node that triggered the event.

  $target = $(target); // wraps the node in a jQuery object

 if (target.nodeName === 'LI') {

  $target.addClass('clicked');  // do stuff

 }

});

父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。

8、消除查询浪费

虽然jQuery对没有找到任何匹配的elements处理的很好,但是它还是需要花费时间去查找的。如果你的站点有一个全局的JavaScript,你可能会把每个jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要这样做。只去放一些页面上适合用到的function。这样做最有效的方式是你的模板可以完全控制任何时候或者地方执行JavaScript以内联脚 本的方式初始化function。例如,在你的“article”页面模板里,你可能在body标签关闭之前包含以下代码

<script type="text/javascript>mylib.article.init();</script></body& gt;如果你的页面模板包含多种有可能在页面或者不在页面上的模块,或者为了可视化效果你需要它们稍后再初如化,你应该在这些模块之后立即放置初如化函数。

<ul id="traffic_light">

 <li><input type="radio" class="on" name="light" value="red" /> Red</li>

 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

 <li><input type="radio" class="off" name="light" value="green" /> Green</li>

</ul>



<script type="text/javascript>mylib.traffic_light.init();</script>

你的全局JavaScript库看起来应该是这样的:

var mylib ={

 article_page : {

  init : function()  {

   // Article page specific jQuery functions. 

  }

 }, 

 traffic_light : {

  init : function()  {

   // Traffic light specific jQuery functions. 

  }

 }

}

9、遵从$(windows).load

有 一种诱惑会使jQuery开发者hook所有事情到 $(document).ready 这个虚伪的事件里。毕竟在大多数例子里都可以看到这样使用。虽然$(document).ready 非常有用,它在页面呈现时发生,虽然其它对象还在下载中。如果你发现你的页面在下载中停顿,就有可能是$(document).ready 引起的。你可以通过把jQuery functions帮定到$(window).load事件来减少下面下载时的CPU使用率,它是在所有HTML(包括iframe内容)都下载完以后才 去调用所有对象的。

$(window).load(function(){

 // jQuery functions to initialize after the page has loaded.

});

多余的功能,如拖拽、帮定可视化效果和动画、预读取图片等,使用这种方法比较好。

10、压缩JS

虽然和jQuery无关,但在这里也要提一下。使JavaScript函数和变量变得可读是一个趋势,这对开发者来讲是必不可少的,但对普通用户来 讲没有任何关系。不用什么借口,是时候把JS压缩纳入我们的工作流程中来了。注释你的代码,在投放到生产环境之前找一个压缩工具进行压缩。使用 YUICompressor 压缩你代码中多余的浪费的字节。根据我们的经验,它可以安全的把JavaScript压缩的尽可能小,而不会多占用CPU。小提示:为了在 YUICompressor里最大化压缩,应该这样这样定义变量(例如:var my_long_variable_name;)

学习和最有效的使用jQuery,最好的方法就是去查jQuery的文档和手册了。

以上就是本文的全部内容,了解更多jQuery的语法,大家可以查看:《jQuery 1.10.3 在线手册》,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript offsetX与layerX区别
Mar 12 Javascript
jQuery Lightbox 图片展示插件使用说明
Apr 25 Javascript
window.location.reload()方法刷新页面弹出要再次显示该网页对话框
Apr 24 Javascript
jquery封装的对话框简单实现
Jul 21 Javascript
javascript判断是否按回车键并解决浏览器之间的差异
May 13 Javascript
自定义函数实现IE7与IE8不兼容js中trim函数的问题
Feb 03 Javascript
JavaScript实现点击单元格改变背景色的方法
Feb 12 Javascript
详解React中的组件通信问题
Jul 31 Javascript
es6系列教程_ Map详解以及常用api介绍
Sep 25 Javascript
js中的reduce()函数讲解
Jan 18 Javascript
微信小程序实现菜单左右联动
May 19 Javascript
JavaScript最完整的深浅拷贝实现方式详解
Feb 28 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
Jun 21 #Javascript
JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
Jun 21 #Javascript
JavaScript检测原始值、引用值、属性
Jun 20 #Javascript
Js 获取当前函数参数对象的实现代码
Jun 20 #Javascript
JS实现鼠标框选效果完整实例
Jun 20 #Javascript
javascript事件冒泡简单示例
Jun 20 #Javascript
JS实现的打字机效果完整实例
Jun 20 #Javascript
You might like
在PHP中使用反射技术的架构插件使用说明
2010/05/18 PHP
php截取字符串函数substr,iconv_substr,mb_substr示例以及优劣分析
2014/06/10 PHP
THINKPHP3.2使用soap连接webservice的解决方法
2017/12/13 PHP
C#中TrimStart,TrimEnd,Trim在javascript上的实现
2011/01/17 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
2014/10/31 Javascript
简述JavaScript中正则表达式的使用方法
2015/06/15 Javascript
详解JavaScript中localStorage使用要点
2016/01/13 Javascript
解决拦截器对ajax请求的拦截实例详解
2016/12/21 Javascript
JavaScript实现移动端轮播效果
2017/06/06 Javascript
深入理解vue.js中的v-if和v-show
2017/06/22 Javascript
详解在 Angular 项目中添加 clean-blog 模板
2017/07/04 Javascript
JS开发中基本数据类型具体有哪几种
2017/10/19 Javascript
使用Electron构建React+Webpack桌面应用的方法
2017/12/15 Javascript
node.js实现为PDF添加水印的示例代码
2018/12/05 Javascript
使用pm2自动化部署node项目的方法步骤
2019/01/28 Javascript
用Python的Django框架完成视频处理任务的教程
2015/04/02 Python
简介Django框架中可使用的各类缓存
2015/07/23 Python
python实现发送邮件功能代码
2017/12/14 Python
python3.5基于TCP实现文件传输
2020/03/20 Python
Django之使用celery和NGINX生成静态页面实现性能优化
2019/10/08 Python
python 读取数据库并绘图的实例
2019/12/03 Python
Python 判断时间是否在时间区间内的实例
2020/05/16 Python
pyx文件 生成pyd 文件用于 cython调用的实现
2021/03/04 Python
GANT葡萄牙官方商店:拥有美国运动服传统的生活方式品牌
2018/10/18 全球购物
城市规划毕业生求职信
2013/10/10 职场文书
爷爷追悼会答谢词
2014/01/24 职场文书
企业宣传口号
2014/06/12 职场文书
先进班集体事迹材料
2014/12/25 职场文书
2015年学校工作总结范文
2015/04/20 职场文书
安全教育片观后感
2015/06/17 职场文书
倡议书怎么写?
2019/04/11 职场文书
解决Go gorm踩过的坑
2021/04/30 Golang
MySQL一些常用高级SQL语句
2021/07/03 MySQL
redis客户端实现高可用读写分离的方式详解
2021/07/04 Redis
Python实战实现爬取天气数据并完成可视化分析详解
2022/06/16 Python