jQuery选择器的工作原理和优化分析


Posted in Javascript onJuly 25, 2011

每次申明一个jQuery对象的时候,返回的是jQuery.prototype.init 对象,很多人就会不明白,init明明是jQuery.fn的方法啊,实际上这里不是方法,而是init的构造函数,因为js的prototype对象可 以实现继承,加上js的对象只是引用不会是拷贝,new jQuery,new jQuery.fn和new jQuery.fn.init的子对象是一样的,只是有没有执行到init的不同,这里就不讲原因了,等下一篇再讲为什么会是这样。
当我们使用选择器的时候$(selector,content),就会执行 init(selectot,content),我们看看inti中是怎样执行的:

if ( typeof selector == "string" ) { 
//正则匹配,看是不是HTML代码或者是#id 
var match = quickExpr.exec( selector ); 
//没有作为待查找的 DOM 元素集、文档或 jQuery 对象。 
//selector是#id的形式 
if ( match && (match[1] || !context) ) { 
// HANDLE: $(html) -> $(array) 
//HTML代码,调用clean补全HTML代码 
if ( match[1] ){ 
selector = jQuery.clean( [ match[1] ], context ); 
} 
// 是: $("#id") 
else { 
//判断id的Dom是不是加载完成 
var elem = document.getElementById( match[3] ); 
if ( elem ){ 
if ( elem.id != match[3] ) 
return jQuery().find( selector ); 
return jQuery( elem );//执行完毕return 
} 
selector = []; 
} 
//非id的形式.在context中或者是全文查找 
} else{ 
return jQuery( context ).find( selector ); 
} 
}

这里就说明只有选择器写成$(‘#id')的时候最快,相当于执行了一次 getElementById,后边的程序就不用再执行了。当然往往我们需要的选择器并不是这么简单,比如我们需要id下的CSS为className, 有这样的写法$(‘#id.className')和$(‘#id').find(‘.className');这两种写法的执行结果都是一样的,比 如<div id=”id”><span class=”className”></span></div>,返回的肯定都是<span class=”className”></span>,但是执行的效率是完全不一样的。
在分析一下上边的代码,如果不是$(‘#id')这样的简单选择器的话,都会执行find函 数,那我们再看看find到底是做用的:
find: function( selector ) { 
//在当前的对象中查找 
var elems = jQuery.map(this, function(elem){ 
return jQuery.find( selector, elem ); 
}); 
//下边的代码可以忽略,只是做一些处理 
//这里应用了js的正则对象的静态方法test 
//indexOf("..")需要了解一下xpath的语法,就是判断selector中包含父节点的写法 
//本意就是过滤数组的重复元素 
return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? 
jQuery.unique( elems ) : 
elems ); 
}

如果这样写$(‘#id .className'),就会执行到扩展的find(‘#id .className',document),因为当前的this是document的jQuery数组,那我们在看看扩展的find他的实现,代码比较 多,就不列出来,总之就是从第二个参数传递进行的dom第一个子节点开始找,遇见#比对id,遇见.比对ClassName,还有:<+-等处理。 那我们要优化,是不是就要想办法让第二个参数context的范围最小,那样遍历是不是就很少了?
如果我们这样写$(‘#id').find(‘.className'),那程序只这样执行 的,第一次init的时候执行一步getElementById,就return了,接着执行 find(‘.className',divDocument),divDocument就是我们第一次选择的是div标签,如果document下有很 多dom对象的时候,这次只遍历divDocument是不是少了很多次,而且在第一次选择id的速度也要比遍历快的多。
现在大家应该是明白了吧。就是说第一层选择最好是ID,而是简单选择器,目的就是定义范围, 提高速度,这次就说这些,选择写法的优化,其他的优化,下次再说。
Javascript 相关文章推荐
通过下拉框的值来确定输入框是否可以为空的代码
Oct 18 Javascript
json对象转字符串如何实现
Dec 02 Javascript
js动态调用css属性的小规律及实例说明
Dec 28 Javascript
AngularJs Managing Service Dependencies详解
Sep 02 Javascript
JavaScript三种绑定事件方式及相互之间的区别分析
Jan 10 Javascript
jquery 手势密码插件
Mar 17 Javascript
Node.js  REPL (交互式解释器)实例详解
Aug 06 Javascript
vue mounted组件的使用
Jun 18 Javascript
微信小程序使用canvas的画图操作示例
Jan 18 Javascript
jquery实现直播弹幕效果
Nov 28 jQuery
在Vue中使用antv的示例代码
Jun 29 Javascript
Vue项目打包、合并及压缩优化网页响应速度
Jul 07 Vue.js
Jquery 点击按钮显示和隐藏层的代码
Jul 25 #Javascript
multiSteps 基于Jquery的多步骤滑动切换插件
Jul 22 #Javascript
JavaScript实现页面滚动图片加载(仿lazyload效果)
Jul 22 #Javascript
JS 自定义带默认值的函数
Jul 21 #Javascript
表单切换,用回车键替换Tab健(不支持IE)
Jul 20 #Javascript
在浏览器中获取当前执行的脚本文件名的代码
Jul 19 #Javascript
iframe 异步加载技术及性能分析
Jul 19 #Javascript
You might like
PHP.MVC的模板标签系统(三)
2006/09/05 PHP
php imagecreatetruecolor 创建高清和透明图片代码小结
2010/05/15 PHP
关于php curl获取301或302转向的网址问题的解决方法
2011/06/02 PHP
php curl 获取https请求的2种方法
2015/04/27 PHP
php根据日期或时间戳获取星座信息和生肖等信息
2015/10/20 PHP
JavaScript时间转换处理函数
2015/04/14 Javascript
jQuery获得子元素个数的方法
2015/04/14 Javascript
jQuery横向擦除焦点图特效代码分享
2015/09/06 Javascript
微信小程序 支付功能开发错误总结
2017/02/21 Javascript
vue 组件的封装之基于axios的ajax请求方法
2018/08/11 Javascript
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
2018/09/04 Javascript
JS数据类型(基本数据类型、引用数据类型)及堆和栈的区别分析
2020/03/04 Javascript
简介JavaScript错误处理机制
2020/08/04 Javascript
toString.call()通用的判断数据类型方法示例
2020/08/28 Javascript
整理Python中的赋值运算符
2015/05/13 Python
Python基础中所出现的异常报错总结
2016/11/19 Python
python实现杨辉三角思路
2017/07/14 Python
Python多进程multiprocessing用法实例分析
2017/08/18 Python
解决python 文本过滤和清理问题
2019/08/28 Python
Pycharm中出现ImportError:DLL load failed:找不到指定模块的解决方法
2019/09/17 Python
Python求平面内点到直线距离的实现
2020/01/19 Python
纯css3制作的火影忍者写轮眼开眼至轮回眼及进化过程实例
2014/11/11 HTML / CSS
英国最大的电子零件及配件零售商:Partmaster
2017/04/24 全球购物
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
德尔福集团DELPHI的笔试题
2012/02/22 面试题
大学生标准推荐信范文
2013/11/25 职场文书
打架检讨书100字
2014/01/08 职场文书
十岁生日同学答谢词
2014/01/19 职场文书
2014年幼儿园教研工作总结
2014/12/04 职场文书
会议通知格式范文
2015/04/15 职场文书
2016年小学六一儿童节活动总结
2016/04/06 职场文书
创业计划书之面包店
2019/09/12 职场文书
创业计划书之韩国烧烤店
2019/09/19 职场文书
浅谈Redis的几个过期策略
2021/05/27 Redis
MySQL创建管理HASH分区
2022/04/13 MySQL
Windows Server 2008 修改远程登录端口以及配置防火墙
2022/04/28 Servers