基于jQuery查找dom的多种方式性能问题

这个问题的产生由于我们前端组每个人的编码习惯的差异,最主要的还是因为代码的维护性问题。在此基础上,我对jQuery源码(1.11.3)查找dom节点相关的内容进行了仔细的查阅,虽然并不能理解的很深入 。。同时基于对浏览器console对象的了解产生了一系列之后的问题和分析,对jQuery最常用的三种dom查找方式进行了一个查找效率和性能方面的比较分析。

首先我们要用到的是   console.time()   和   console.timeEnd()   这两个成对出现的console对象的方法,该方法的用法是将他们两者之间的代码段执行并输出所消耗的执行时间,并且两者内传入的字符串命名须统一才能生效,例如:

1 console.time(‘Scott‘);
2 console.log(‘seven‘);
3 console.timeEnd(‘Scott‘);
4 seven5 Scott: 0.256ms

代码段中三处一致才是正确的用法。

接下来我们来讨论我们常用的jQuery查找dom方式:

  1. $(‘.parent .child‘);

  2. $(‘.parent‘).find(‘.child‘);

  3. $(‘.child‘,‘.parent‘);

其中方式1和方式3都是基于jQuery的selector和context的查找方式,既我们最常用的jQuery()或者$(),

详细即为:

1 jQuery = function( selector, context ) {
2     // The jQuery object is actually just the init constructor ‘enhanced‘
3     // Need init if jQuery is called (just allow error to be thrown if not included)
4     return new jQuery.fn.init( selector, context );
5 }

基于jQuery(1.11.3)70行处,为该方法的入口,他做的所有事情就是创建了一个jquery.fn上的init方法的对象,我们再来细看这个对象是什么:

  1     init = jQuery.fn.init = function( selector, context ) {
  2         var match, elem;
  3
  4         // HANDLE: $(""), $(null), $(undefined), $(false)
  5         if ( !selector ) {
  6             return this;
  7         }
  8
  9         // Handle HTML strings
 10         if ( typeof selector === "string" ) {
 11             if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
 12                 // Assume that strings that start and end with <> are HTML and skip the regex check
 13                 match = [ null, selector, null ];
 14
 15             } else {
 16                 match = rquickExpr.exec( selector );
 17             }
 18
 19             // Match html or make sure no context is specified for #id
 20             if ( match && (match[1] || !context) ) {
 21
 22                 // HANDLE: $(html) -> $(array)
 23                 if ( match[1] ) {
 24                     context = context instanceof jQuery ? context[0] : context;
 25
 26                     // scripts is true for back-compat
 27                     // Intentionally let the error be thrown if parseHTML is not present
 28                     jQuery.merge( this, jQuery.parseHTML(
 29                         match[1],
 30                         context && context.nodeType ? context.ownerDocument || context : document,
 31                         true
 32                     ) );
 33
 34                     // HANDLE: $(html, props)
 35                     if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
 36                         for ( match in context ) {
 37                             // Properties of context are called as methods if possible
 38                             if ( jQuery.isFunction( this[ match ] ) ) {
 39                                 this[ match ]( context[ match ] );
 40
 41                             // ...and otherwise set as attributes
 42                             } else {
 43                                 this.attr( match, context[ match ] );
 44                             }
 45                         }
 46                     }
 47
 48                     return this;
 49
 50                 // HANDLE: $(#id)
 51                 } else {
 52                     elem = document.getElementById( match[2] );
 53
 54                     // Check parentNode to catch when Blackberry 4.6 returns
 55                     // nodes that are no longer in the document #6963
 56                     if ( elem && elem.parentNode ) {
 57                         // Handle the case where IE and Opera return items
 58                         // by name instead of ID
 59                         if ( elem.id !== match[2] ) {
 60                             return rootjQuery.find( selector );
 61                         }
 62
 63                         // Otherwise, we inject the element directly into the jQuery object
 64                         this.length = 1;
 65                         this[0] = elem;
 66                     }
 67
 68                     this.context = document;
 69                     this.selector = selector;
 70                     return this;
 71                 }
 72
 73             // HANDLE: $(expr, $(...))
 74             } else if ( !context || context.jquery ) {
 75                 return ( context || rootjQuery ).find( selector );
 76
 77             // HANDLE: $(expr, context)
 78             // (which is just equivalent to: $(context).find(expr)
 79             } else {
 80                 return this.constructor( context ).find( selector );
 81             }
 82
 83         // HANDLE: $(DOMElement)
 84         } else if ( selector.nodeType ) {
 85             this.context = this[0] = selector;
 86             this.length = 1;
 87             return this;
 88
 89         // HANDLE: $(function)
 90         // Shortcut for document ready
 91         } else if ( jQuery.isFunction( selector ) ) {
 92             return typeof rootjQuery.ready !== "undefined" ?
 93                 rootjQuery.ready( selector ) :
 94                 // Execute immediately if ready is not present
 95                 selector( jQuery );
 96         }
 97
 98         if ( selector.selector !== undefined ) {
 99             this.selector = selector.selector;
100             this.context = selector.context;
101         }
102
103         return jQuery.makeArray( selector, this );
104     }

基于jQuery(1.11.3) 2776行处,该方法比较长,我就来大概说一下我对这个方法的了解:这里主要就是做了先对selector的判断,在判断完后,查找context如果存在就继续做对有context存在情况的处理,没有则进行没有context情况的处理,而方式1和方式3:

  1. $(‘.parent .child‘);

  3. $(‘.child‘,‘.parent‘);

他们都要进入相同的判断步骤,即上面简要说明的判断流程,等到1和3判断完后所花费的时间基本差不多,但是1内部的选择器还需要花费时间去查找,得出

  方式1. $(‘.parent .child‘);  走完流程花费的时间:a;

  方式3. $(‘.child‘,‘.parent‘);  走完流程花费的时间:a; 几乎已经找到dom节点

方式1. $(‘.parent .child‘);  查找选择器.parent .child花费的时间:b;

所以得出初步结论:方式3. $(‘.child‘,‘.parent‘);花费的时间:a;    方式1. $(‘.parent .child‘);花费的时间:a + b;  方式3优于方式1

接下来我们来看实际的运行结果:

以百度页面为例,我们随便找出一组满足的范围来查找,博主进行多次测试,方式3的查找效率均快于方式1,且方式3的查找速度基本为方式1的3倍左右,即:

接下来我们我们加入jQuery的find方法进行比较,即为:

  方式1. $(‘.parent .child‘);

  方式2. $(‘.parent‘).find(‘.child‘);

  方式3. $(‘.child‘,‘.parent‘);

由于我们已有了之前的判断,基于他们三者都要进行jQuery()的查找,所以三者都在此花费a的查找时间,此时方式3已经基本找到了:

  方式3. $(‘.child‘,‘.parent‘); 花费时间:a;

接下来方式1进行 ‘.parent .child‘选择器的查找,方式2进行jQuery的find方法查找,在此列出find的具体内容:

 1 find: function( selector ) {
 2         var i,
 3             ret = [],
 4             self = this,
 5             len = self.length;
 6
 7         if ( typeof selector !== "string" ) {
 8             return this.pushStack( jQuery( selector ).filter(function() {
 9                 for ( i = 0; i < len; i++ ) {
10                     if ( jQuery.contains( self[ i ], this ) ) {
11                         return true;
12                     }
13                 }
14             }) );
15         }
16
17         for ( i = 0; i < len; i++ ) {
18             jQuery.find( selector, self[ i ], ret );
19         }
20
21         // Needed because $( selector, context ) becomes $( context ).find( selector )
22         ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
23         ret.selector = this.selector ? this.selector + " " + selector : selector;
24         return ret;
25     }

基于jQuery(1.11.3) 2716行处,在此我们可以看出find的过程比较简单,相较于方式1查找复杂的选择器(在查找选择器的过程中需要排除很多的情况,更多的时间花费在处理字符串上,即处理出我们想要表达的选择器)更高效一点,我们得出方式2优于方式1,下面我们拿三者来进行比较:

我们可以看出,方式1最慢,方式2和方式3不相上下,方式3略胜一筹,基本吻合我们的初衷,即为:

在基于jQuery查找dom的过程中能使用jquery的查找方式就使用,尽量不写复杂的选择器来表达我们想要查找的dom,效率极低。相反使用jquery的查找方式我们就能尽量排除复杂选择器的情况,极大提高查找效率。

由于方式2的使用可能会受限,所以在此我推荐大家使用方式3,即为:

  

写到这里,突然感觉好像对自己并没有什么(luan)用,写的好像我的编码能力已经强到了来拼dom查找效率的地步 。。。

原创,转载请注明。by Scott.

时间: 2024-10-17 16:49:34

基于jQuery查找dom的多种方式性能问题的相关文章

基于jquery多种切换效果的焦点图(兼容ie6)

随着html5和css3的诞生.各种非常酷.非常炫的网页焦点图在各个前端技术网上满天飞.基于html5和css3技术的焦点图有一个弊端就是要在ie9以上才支持.这让需兼容ie6到ie8的页面又爱又恨.下面为大家介绍一款完全基于juery的焦点图,而且这款插件完美支持ie6,多种百叶窗切换,效果还是相当赏目的.无图无真相,还是先上图 点击这里在线预览 点击这里下载源码 使用教程 这款插件代码很简洁,使用也非常简单.看截图 ok.今天就和大家分享到这里.周末好快,作为一名码农真是苦逼,明天还要早起,

jQuery绑定事件-多种方式实现

jQuery绑定事件-多种方式实现: <html> <head> <meta charset="utf-8" /> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script><!--百度CDN--> </head> <body> <input type="text"/&

基于jquery多种切换效果的焦点图(兼容ie6)

这款插件代码很简洁,使用也非常简单.看截图 转载来源地址:http://www.cnblogs.com/liaohuolin/articles/3918144.html 基于jquery多种切换效果的焦点图(兼容ie6)

基于jQuery 常用WEB控件收集

Horizontal accordion: jQuery 基于jQuery开发,非常简单的水平方向折叠控件. Horizontal accordion: jQuery jQuery-Horizontal Accordion 具有XBOX360 blade界面风格的水平方向Accordion. jQuery-Horizontal Accordion AutoComplete-JQuery jQuery插件易于集成到现在的表单中(Form). AutoComplete-JQuery Facebook

基于jquery的城市选择插件

城市选择插件的难度不是很大,主要是对dom节点的操作.而我写的这个插件相对功能比较简答,没有加入省市联动. 上代码好了,参照代码的注释应该比较好理解. 1 /* 2 *基于jquery的城市选择插件 3 *author:youziclub 4 *2015-4-22 5 */ 6 ;(function($){ 7 $.fn.city=function(options){ 8 // 城市信息 9 var nav=['热门','A-G','H-L','M-T','W-Z','其他']; 10 var

三、jquery操作DOM

DOM(Document Object Model, 文档对象模型)为文档提供了一种结构化的表示方法,通过该方法可以改变文档的内容和展示形式.在实际运用中,DOM更像是桥梁,通过它可以实现跨平台.跨语言的标准访问. 与DOM密不可分的是javascript脚本技术,DOM在客户端的技术也是基于该技术,通过该技术我们可以很方便的访问.检索.操作文档中的任何一个元素.因此,学号javascript脚本技术,是掌握DOM对象的一个重要条件. Document即文档,当我们创建一个页面并加载到浏览器时,

一些基于jQuery开发的控件

基于jQuery开发,非常简单的水平方向折叠控件.主页:http://letmehaveblog.blogspot.com/2007/10/haccordion-simple-horizontal-accordion.html (无法找到)下载:http://letmehaveblog.blogspot.com/2007/10/haccordion-simple-horizontal-accordion.html 示例:http://letmehaveblog.blogspot.com/2007

基于jquery开发的UI框架整理分析

根据调查得知,现在市场中的UI框架差不多40个左右,不知大家都习惯性的用哪个框架,现在市场中有几款UI框架稍微的成熟一些,也是大家比较喜欢的一种UI框架,那应该是jQuery,有部分UI框架都是根据jQuery研发出来的产品,现在也很常见了. 国产jQuery UI框架 (jUI) DWZ DWZ富客户端框架(jQuery RIA framework), 是中国人自己开发的基于jQuery实现的Ajax RIA开源框架.设计目标是简单实用,快速开发,降低ajax开发成本. jQuery 部件布局

基于jquery的ajax分页插件(demo+源码)

前几天打开自己的博客园主页,无意间发现自己的园龄竟然有4年之久了.可是看自己的博客列表却是空空如也,其实之前也有写过,但是一直没发布(然而好像并没有什么卵用).刚开始学习编程时就接触到博客园,且在博客园学习了很多的知识,看过很多人的分享.说来也惭愧,自己没能为园友们分享自己的所学所得(毕竟水平比较差). 过去的一年也是辗转了几个城市换了几份工作(注定本命年不太平?).八月份来到现在所在的公司(OTA行业),公司是做互联网的,所以可能大家的前端都屌屌的?之前一直从事.NET开发(现在在这边也是),