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 相关文章推荐
jQuery的实现原理的模拟代码 -3 事件处理
Aug 03 Javascript
基于jquery的多功能软键盘插件
Jul 25 Javascript
JQuery实现简单时尚快捷的气泡提示插件
Dec 20 Javascript
jquery ajax实现下拉框三级无刷新联动,且保存保持选中值状态
Oct 29 Javascript
jquery自动填充勾选框即把勾选框打上true
Mar 24 Javascript
JavaScript学习笔记之JS事件对象
Jan 22 Javascript
基于javascript实现右下角浮动广告效果
Jan 08 Javascript
BootStrap创建响应式导航条实例代码
May 31 Javascript
vue里面v-bind和Props 利用props绑定动态数据的方法
Aug 27 Javascript
QML实现圆环颜色选择器
Sep 25 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
Dec 02 Javascript
vue基础知识--axios合并请求和slot
Jun 04 Javascript
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文本操作类
2006/11/25 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
PHP将字符分解为多个字符串的方法
2014/11/22 PHP
php中$_POST与php://input的区别实例分析
2015/01/07 PHP
php+mysql查询实现无限下级分类树输出示例
2016/10/03 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
PHP laravel中的多对多关系实例详解
2017/06/07 PHP
Laravel框架之解决前端显示图片问题
2019/10/24 PHP
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
2015/10/28 Javascript
js浏览器html5表单验证
2016/10/17 Javascript
RequireJS简易绘图程序开发
2016/10/28 Javascript
Vue框架中正确引入JS库的方法介绍
2017/07/30 Javascript
原生JS 购物车及购物页面的cookie使用方法
2017/08/21 Javascript
es6学习之解构时应该注意的点
2017/08/29 Javascript
vue.js实例对象+组件树的详细介绍
2017/10/20 Javascript
js实现前面自动补全位数的方法
2018/10/10 Javascript
vue下的@change事件的实现
2019/10/25 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
Python yield 使用方法浅析
2017/05/20 Python
virtualenv实现多个版本Python共存
2017/08/21 Python
怎么使用pipenv管理你的python项目
2018/03/12 Python
python使用RNN实现文本分类
2018/05/24 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
Django REST framework 视图和路由详解
2019/07/19 Python
Python基于类路径字符串获取静态属性
2020/03/12 Python
Python调用接口合并Excel表代码实例
2020/03/31 Python
python录音并调用百度语音识别接口的示例
2020/12/01 Python
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
Ticketmaster意大利:音乐会、节日、艺术和剧院的官方门票
2019/12/23 全球购物
盖尔斯工厂店:GUESS Factory
2020/01/21 全球购物
日语专业求职信
2014/07/04 职场文书
经营场所证明范本
2015/06/19 职场文书
2016年小学教师政治学习心得体会
2016/01/23 职场文书
JavaScript实现贪吃蛇游戏
2021/06/16 Javascript
使用 MybatisPlus 连接 SqlServer 数据库解决 OFFSET 分页问题
2022/04/22 SQL Server