前言

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

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

console.time('Scott');
console.log('seven');
console.timeEnd('Scott');
seven
Scott: 0.256ms

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

正文

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

1.$(‘.parent .child');
2.$(‘.parent').find(‘.child');
3.$(‘.child','.parent');

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

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

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

init = jQuery.fn.init = function( selector, context ) {
 var match, elem;

 // HANDLE: $(""), $(null), $(undefined), $(false)
 if ( !selector ) {
 return this;
 }

 // Handle HTML strings
 if ( typeof selector === "string" ) {
 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
 // Assume that strings that start and end with <> are HTML and skip the regex check
 match = [ null, selector, null ];

 } else {
 match = rquickExpr.exec( selector );
 }

 // Match html or make sure no context is specified for #id
 if ( match && (match[1] || !context) ) {

 // HANDLE: $(html) -> $(array)
 if ( match[1] ) {
 context = context instanceof jQuery ? context[0] : context;

 // scripts is true for back-compat
 // Intentionally let the error be thrown if parseHTML is not present
 jQuery.merge( this, jQuery.parseHTML(
 match[1],
 context && context.nodeType ? context.ownerDocument || context : document,
 true
 ) );

 // HANDLE: $(html, props)
 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
 for ( match in context ) {
 // Properties of context are called as methods if possible
 if ( jQuery.isFunction( this[ match ] ) ) {
 this[ match ]( context[ match ] );

 // ...and otherwise set as attributes
 } else {
 this.attr( match, context[ match ] );
 }
 }
 }

 return this;

 // HANDLE: $(#id)
 } else {
 elem = document.getElementById( match[2] );

 // Check parentNode to catch when Blackberry 4.6 returns
 // nodes that are no longer in the document #6963
 if ( elem && elem.parentNode ) {
 // Handle the case where IE and Opera return items
 // by name instead of ID
 if ( elem.id !== match[2] ) {
 return rootjQuery.find( selector );
 }

 // Otherwise, we inject the element directly into the jQuery object
 this.length = 1;
 this[0] = elem;
 }

 this.context = document;
 this.selector = selector;
 return this;
 }

 // HANDLE: $(expr, $(...))
 } else if ( !context || context.jquery ) {
 return ( context || rootjQuery ).find( selector );

 // HANDLE: $(expr, context)
 // (which is just equivalent to: $(context).find(expr)
 } else {
 return this.constructor( context ).find( selector );
 }

 // HANDLE: $(DOMElement)
 } else if ( selector.nodeType ) {
 this.context = this[0] = selector;
 this.length = 1;
 return this;

 // HANDLE: $(function)
 // Shortcut for document ready
 } else if ( jQuery.isFunction( selector ) ) {
 return typeof rootjQuery.ready !== "undefined" ?
 rootjQuery.ready( selector ) :
 // Execute immediately if ready is not present
 selector( jQuery );
 }

 if ( selector.selector !== undefined ) {
 this.selector = selector.selector;
 this.context = selector.context;
 }

 return jQuery.makeArray( selector, this );
 }

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

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

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

  • 方式1. $(‘.parent .child'); 走完流程花费的时间:a;
  • 方式3. $(‘.child','.parent'); 走完流程花费的时间:a; 几乎已经找到dom节点
  • 方式1. $(‘.parent .child'); sizzle相关查找选择器.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的具体内容:

find: function( selector ) {
 var i,
 ret = [],
 self = this,
 len = self.length;

 if ( typeof selector !== "string" ) {
 return this.pushStack( jQuery( selector ).filter(function() {
 for ( i = 0; i < len; i   ) {
  if ( jQuery.contains( self[ i ], this ) ) {
  return true;
  }
 }
 }) );
 }

 for ( i = 0; i < len; i   ) {
 jQuery.find( selector, self[ i ], ret );
 }

 // Needed because $( selector, context ) becomes $( context ).find( selector )
 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
 ret.selector = this.selector ? this.selector   " "   selector : selector;
 return ret;
 }

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

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

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

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


总结

好了,以上就是这篇文文章的全部内容了,写到这里,突然感觉好像对自己并没有什么(luan)用,写的好像我的编码能力已经强到了来拼dom查找效率的地步 。希望能对有需要的朋友们有一定的帮助吧。

jQuery查找dom的几种方法效率详解的更多相关文章

  1. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS 10 Safari问题在DOM中不再包含元素

    使用此链接,您可以重现该错误.https://jsfiddle.net/pw7e2j3q/如果您点击元素并从dom中删除它,然后单击链接测试.你应该看到旧的元素弹出选择.是否有一些黑客来解决这个问题?解决方法我能够重现这个问题.问题是,每当您尝试删除其更改事件上的选择框时,iOS10都无法正确解除对选择框的绑定.要解决此问题,您需要将代码更改事件代码放在具有一些超时

  3. ios – Cordova 3.7在每个本机通话中复制iframe

    由于我已升级到Cordova3.7,每个本地调用都将一个新的iframe附加到DOM,如下所示.为了排除我现有的代码影响cordova的可能性,我尝试使用cordovaCLI创建一个新的代码,添加控制台插件,并在设备控制台中的setInterval循环中调用console.log().因此,我在DOM中收到了大量的iframe.我在iPad3,iOS7上尝试过使用xCode6构建应用程序.有没有人遇到这个问题?

  4. 在IOS9中的Cordova应用程序使用JQuery / Javascript的window.history问题

    在两个测试用例中唯一改变的是Cordova.js.解决方法我看到这是几个星期前,但我会发布这个,以防其他人遇到它.听起来它可能与iOS9中的哈希更改生成的导航事件有关.如果是这样,可以将其添加到index.html以禁用哈希侦听:

  5. iOS 5上的jQuery事件

    解决方法在Apple开发论坛上由一个人回答:我需要在将元素添加到DOM之后才绑定(),如下所示:

  6. android – 区别:SAX Parser,XPath,DOM,XMLPullParser

    ,但Dom允许您访问xml文件的任何部分,因为它将整个文件/文档保存在内存中.看到这个article,你可以通过阅读摘要得到你想要的.另请查看此link以查看不同xml解析器的性能

  7. android – Phonegap本地构建 – jquery ajax错误:readystate 0 responsetext status 0 statustext error

    解决方法您是否在索引文件中包含了内容安全元标记?

  8. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  9. 设置焦点到输入框和显示Android键盘使用jquery手机在pageshow

    我正在设置焦点到输入框,并显示Android键盘使用jquery手机网页显示.我从Web上尝试过很多选项.但是没有一个在模拟器和移动设备中都能按预期工作.这是代码:查找屏幕截图以供参考请咨询…解决方法对我有用的解决方案

  10. android – 如何在焦点()上以编程方式隐藏jquery mobile中的键盘

    我想在Focus()上隐藏键盘,但是当$(“.ui-input-text”).focus();它会自动打开键盘.我只是想隐藏在特定的屏幕上,我用document.activeElement.blur()测试;但它也没有关注()输入.解决方法提交表单时,iOS键盘可能不会自动关闭.这是一个非常实用的问题,因为不应要求用户手动关闭键盘,否则他们不会期望需要这样做.可以通过调用document.acti

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部