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 相关文章推荐
JS 添加网页桌面快捷方式的代码详细整理
Dec 27 Javascript
Javascript的严格模式strict mode详细介绍
Jun 06 Javascript
node.js中的buffer.slice方法使用说明
Dec 10 Javascript
js实现点击链接后窗口缩小并居中的方法
Mar 02 Javascript
javascript中基本类型和引用类型的区别分析
May 12 Javascript
可以浮动某个物体的jquery控件用法实例
Jul 24 Javascript
详解JS去重及字符串奇数位小写转大写
Dec 29 Javascript
vue指令以及dom操作详解
Mar 04 Javascript
JS基于正则实现数字千分位用逗号分隔的方法
Jun 16 Javascript
原生JavaScript实现Ajax异步请求
Nov 19 Javascript
vue+express+jwt持久化登录的方法
Jun 14 Javascript
如何在Vue中使localStorage具有响应式(思想实验)
Jul 14 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
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
php之curl设置超时实例
2014/11/03 PHP
thinkphp5实现无限级分类
2019/02/18 PHP
jquery 获取json数据实现代码
2009/04/27 Javascript
javascript 子窗体父窗体相互传值方法
2010/05/31 Javascript
js判断游览器类型及版本号的代码
2014/05/11 Javascript
javascript在IE下trim函数无法使用的解决方法
2014/09/12 Javascript
实例详解angularjs和ajax的结合使用
2015/10/22 Javascript
PassWord输入框代码分享
2016/06/07 Javascript
JS实现探测网站链接的方法【测试可用】
2016/11/08 Javascript
flag和jq on 的绑定多个对象和方法(必看)
2017/02/27 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
解决vue-cli + webpack 新建项目出错的问题
2018/03/20 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
Vue2 监听属性改变watch的实例代码
2018/08/27 Javascript
基于Angular中ng-controller父子级嵌套的相关属性详解
2018/10/08 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
Nodejs 微信小程序消息推送的实现
2021/01/20 NodeJs
使用Python的Supervisor进行进程监控以及自动启动
2014/05/29 Python
Python入门篇之条件、循环
2014/10/17 Python
在Django中管理Users和Permissions以及Groups的方法
2015/07/23 Python
Python中Django框架利用url来控制登录的方法
2015/07/25 Python
详解Python中映射类型的内建函数和工厂函数
2015/08/19 Python
Python用for循环实现九九乘法表
2018/05/31 Python
Python企业编码生成系统总体系统设计概述
2019/07/26 Python
学Python 3的理由和必要性
2019/11/19 Python
Python迭代器模块itertools使用原理解析
2019/12/11 Python
解决pycharm debug时界面下方不出现step等按钮及变量值的问题
2020/06/09 Python
Python内存泄漏和内存溢出的解决方案
2020/09/26 Python
python os.rename实例用法详解
2020/12/06 Python
纯CSS3实现滚动的齿轮动画效果
2014/06/05 HTML / CSS
材料加工工程求职信
2014/02/19 职场文书
幼儿园教师的自我评价范文
2014/09/17 职场文书
企业介绍信范文
2015/01/30 职场文书
职场领导同事生日简短祝福语
2019/08/06 职场文书
使用CSS自定义属性实现骨架屏效果
2022/06/21 HTML / CSS