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 相关文章推荐
父窗口获取弹出子窗口文本框的值
Jun 27 Javascript
js 浮动层菜单收藏
Jan 16 Javascript
JavaScript中的object转换成number或string规则介绍
Dec 31 Javascript
使用JS 插件qrcode.js生成二维码功能
Feb 20 Javascript
JavaScript中的遍历详解(多种遍历)
Apr 07 Javascript
JavaScript中offsetWidth的bug及解决方法
May 17 Javascript
JavaScript实现获取用户单击body中所有A标签内容的方法
Jun 05 Javascript
深究AngularJS——ng-checked(回写:带真实案例代码)
Jun 13 Javascript
web3.js增加eth.getRawTransactionByHash(txhash)方法步骤
Mar 15 Javascript
解析vue、angular深度作用选择器
Sep 11 Javascript
JavaScript实现拖拽效果
Mar 16 Javascript
jquery插件实现悬浮的菜单
Apr 24 jQuery
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魔术方法使用方法汇总
2016/02/14 PHP
详解PHP的Yii框架中扩展的安装与使用
2016/04/01 PHP
php基于CodeIgniter实现图片上传、剪切功能
2016/05/14 PHP
PHP模块化安装教程
2016/06/01 PHP
浅谈PHP发送HTTP请求的几种方式
2017/07/25 PHP
php使用json-schema模块实现json校验示例
2019/09/28 PHP
PHP 多进程与信号中断实现多任务常驻内存管理实例方法
2019/10/04 PHP
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
Javascript在IE和FireFox中的不同表现简析
2012/12/03 Javascript
基于Node.js实现nodemailer邮件发送
2016/01/26 Javascript
用js实现放大镜的效果的简单实例
2016/05/23 Javascript
BootStrap 智能表单实战系列(二)BootStrap支持的类型简介
2016/06/13 Javascript
浅谈时钟的生成(js手写简洁代码)
2016/08/20 Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
2017/01/16 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
2018/04/23 Javascript
vue-cli项目无法用本机IP访问的解决方法
2018/09/20 Javascript
vue slot与传参实例代码讲解
2019/04/28 Javascript
React组件设计模式之组合组件应用实例分析
2020/04/29 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
[01:10:03]OG vs EG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
Python操作SQLite数据库的方法详解
2017/06/16 Python
django 通过ajax完成邮箱用户注册、激活账号的方法
2018/04/17 Python
Python实现定制自动化业务流量报表周报功能【XlsxWriter模块】
2019/03/11 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
利用pandas将非数值数据转换成数值的方式
2019/12/18 Python
Python学习之路安装pycharm的教程详解
2020/06/17 Python
HTML+CSS3模拟心的跳动实例代码
2017/09/05 HTML / CSS
美国精油公司:Plant Therapy
2019/05/17 全球购物
数控专业毕业生求职信范文
2013/09/21 职场文书
2014银行领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
求职信格式范文
2015/03/19 职场文书
2015年行政人事部工作总结
2015/05/13 职场文书
2016年国庆节67周年活动总结
2016/04/01 职场文书
python 解决微分方程的操作(数值解法)
2021/05/26 Python
APP界面设计技巧和注意事项
2022/04/29 杂记