各浏览器中querySelector和querySelectorAll的实现差异分析


Posted in Javascript onMay 23, 2012

querySelector和querySelectorAll是W3C提供的新的查询接口

querySelector和querySelectorAll是W3C提供的 新的查询接口,其主要特点如下:

1、querySelector只返回匹配的第一个元素,如果没有匹配项,返回null。
2、querySelectorAll返回匹配的元素集合,如果没有匹配项,返回空的nodelist(节点数组)。
3、返回的结果是静态的,之后对document结构的改变不会影响到之前取到的结果。

这两个方法都可以接受三种类型的参数:id(#),class(.),标签,很像jquery的选择器。

var obj = document.querySelector("#id");var obj = document.querySelector(".classname");
var obj = document.querySelector("div");
var el = document.body.querySelector("style[type='text/css'], style:not([type])");
var elements = document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)");
var elements = document.querySelectorAll("#id1, #id2, .class1, class2, div a, #list li img");

目前IE8+,ff,chrome都支持此api(IE8中的selector string只支持css2.1的)
浏览器支持查看

module dom {
[Supplemental, NoInterfaceObject]
interface NodeSelector {
Element querySelector(in DOMString selectors);
NodeList querySelectorAll(in DOMString selectors);
};
Document implements NodeSelector;
DocumentFragment implements NodeSelector;
Element implements NodeSelector;
};

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 1 3.5 (1.9.1)bug 416317 9 8 (CSS2 selectors only) 10 3.2 (525.3)WebKit bug 16587
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support 2.1 yes 9 10.0 3.2

从接口定义可以看到Document、DocumentFragment、Element都实现了NodeSelector接口。即这三种类型的元素都拥有者两个方法。querySelector和querySelectorAll的参数须是符合 css selector 的字符串。不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)。

目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已经支持它们。

如想获取页面class属性为"red"的元素,除了使用document.getElementsByClassName('red')还可以使用document.querySelector('.red')和document.querySelectorAll('.red')。

但Element.querySelector和Element.querySelectorAll的实现有错误,如下

<div id="d1"> 
<p><a href="http://www.sina.com.cn">SINA</a></p> 
</div> 
<script type="text/javascript"> 
function $(id){return document.getElementById(id);} 
var d1 = $('d1'); 
var obj1 = d1.querySelector('div a'); 
var obj2 = d1.querySelectorAll('div a'); 
alert(obj1); // -> http://www.sina.com.cn/ 
alert(obj2.length); // -> 1 
</script>

如果支持这两个方法的浏览器可以看到分别弹出了“http://www.sina.com.cn/”,和 “1”。说明查询到了想要的元素或元素集合。这与W3C的定义却是不合的,根据定义应该是在元素d1范围内查找"div a",而d1内压根没有div。因此应该分别返回null,空集合。

jQuery1.4.2 及之前版本中只使用了document.querySelectorAll,没有使用Element.querySelectorAll。 jQuery1.4.3 后使用了Element.querySelectorAll,但做了修复。在选择器前加了"#__sizzle__"以强制其在指定元素内查找(3903-3918行)。简化下

function $(id){return document.getElementById(id);} 
var d1 = $('d1'); 
var obj1 = d1.querySelector('div a'); 
var obj2 = d1.querySelectorAll('div a'); 
var old = d1.id, id = d1.id = "__sizzle__"; 
try { 
var query = '#' + id + ' div a'; 
alert(d1.querySelector( query )); 
alert(d1.querySelectorAll( query ).length); 
} catch(e) { 
} finally { 
old ? d1.id = old : d1.removeAttribute( "id" ); 
}

实现很巧妙,指定范围的元素如果有id,将其保留在old,"__sizzle__"赋值其作为临时id,在选择器"div a"前指定查找范围为"#__sizzle__",即d1。finally语句来最后清理,如果指定范围的元素本身有id将其恢复为old,没有则去掉临时的id属性"__sizzle__"。

相关:
http://msdn.microsoft.com/en-us/library/cc288169%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/cc304115%28VS.85%29.aspx
https://developer.mozilla.org/En/DOM/Document.querySelector
https://developer.mozilla.org/En/DOM/Document.querySelectorAll
https://developer.mozilla.org/En/DOM/element.querySelector
https://developer.mozilla.org/En/DOM/Element.querySelectorAll

Javascript 相关文章推荐
IE8提示Invalid procedure call or argument 异常的解决方法
Sep 30 Javascript
MultiSelect左右选择控件的设计与实现介绍
Jun 08 Javascript
iframe子父页面调用js函数示例
Nov 07 Javascript
js实现表单多按钮提交action的处理方法
Oct 24 Javascript
JS实现的表格操作类详解(添加,删除,排序,上移,下移)
Dec 22 Javascript
jQuery插件制作的实例教程
May 16 Javascript
html5+canvas实现支持触屏的签名插件教程
May 08 Javascript
webpack项目调试以及独立打包配置文件的方法
Feb 28 Javascript
详解如何模拟实现node中的Events模块(通俗易懂版)
Apr 15 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
May 13 Javascript
JavaScript中的执行环境和作用域链
Sep 04 Javascript
vue3.0 项目搭建和使用流程
Mar 04 Vue.js
jQuery-onload让第一次页面加载时图片是淡入方式显示
May 23 #Javascript
jquery.pagination.js 无刷新分页实现步骤分享
May 23 #Javascript
jquery.Jwin.js 基于jquery的弹出层插件代码
May 23 #Javascript
使用JQuery和CSS模拟超链接的用户单击事件的实现代码
May 23 #Javascript
基于jquery tab切换(防止页面刷新)
May 23 #Javascript
jQuery下通过replace字符串替换实现大小图片切换
May 22 #Javascript
js面向对象 多种创建对象方法小结
May 21 #Javascript
You might like
PHP中,文件上传
2006/12/06 PHP
php实现 master-worker 守护多进程模式的实例代码
2019/07/20 PHP
PHP swoole和redis异步任务实现方法分析
2019/08/12 PHP
判断用户是否在线的代码
2011/03/05 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
ASP.NET jQuery 实例8 (动态添加内容到DropDownList)
2012/02/03 Javascript
js FLASH幻灯片字符串中有连接符&的处理方法
2012/03/01 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
jquery实现瀑布流效果分享
2014/03/26 Javascript
jQuery中的基本选择器用法学习教程
2016/04/14 Javascript
jquery easyui datagrid实现增加,修改,删除方法总结
2016/05/25 Javascript
JS产生随机数的几个用法详解
2016/06/22 Javascript
工作中比较实用的JavaScript验证和数据处理的干货(经典)
2016/08/03 Javascript
JS检测window.open打开的窗口是否关闭
2017/06/25 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
vue 自定义 select内置组件
2018/04/10 Javascript
vue发送ajax请求详解
2018/10/09 Javascript
python实现的系统实用log类实例
2015/06/30 Python
python format 格式化输出方法
2018/07/16 Python
深入浅析Python2.x和3.x版本的主要区别
2018/11/30 Python
python交互界面的退出方法
2019/02/16 Python
python时间序列按频率生成日期的方法
2019/05/14 Python
基于Python+Appium实现京东双十一自动领金币功能
2019/10/31 Python
python numpy生成等差数列、等比数列的实例
2020/02/25 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
Python生成器实现简单&quot;生产者消费者&quot;模型代码实例
2020/03/27 Python
Django框架配置mysql数据库实现过程
2020/04/22 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
2021/01/05 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
P D PAOLA法国官网:西班牙著名的珠宝首饰品牌
2020/02/15 全球购物
社区国庆节活动方案
2014/02/05 职场文书
律师授权委托书范本
2014/10/07 职场文书
三傻大闹宝莱坞观后感
2015/06/03 职场文书
Java实现简易的分词器功能
2021/06/15 Java/Android
Python中Matplotlib的点、线形状、颜色以及绘制散点图
2022/04/07 Python
python数据处理之Pandas类型转换
2022/04/28 Python