关于这个问题的产生由于我们前端组每个人的编码习惯的差异,最主要的还是因为代码的维护性问题。在此基础上,我对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
接下来我们来看实际的运行结果:
- 下一篇: 赢家经验分享中至万年麻将开挂【好看视频】
- 上一篇: “他得到我们”超级碗广告旨在增加耶稣的相关性