DOM元素querySelectorAll可能让你意外的特性表现
一、时间紧急,废话少说
本文所在的页面藏匿了下面这些代码:
<img id="outside">
<div id="my-id">
<img id="inside">
<div class="lonely"></div>
<div class="outer">
<div class="inner"></div>
</div>
</div>
就是下面这样的表现(为了便于观察,我加了边框背景色和文字):
首先说点大家都知道的热热身。
querySelector和querySelectorAllIE8+浏览器支持。querySelector返回的是单个DOM元素;querySelectorAll返回的是NodeList.- 我们一般用的多的是
document.querySelectorAll, 实际上,也支持dom.querySelectorAll.例如:document.querySelector("#my-id").querySelectorAll("img")选择的就是里面这个妹子。例如,我在控制台输出该选择
NodeList的长度和id,如下截图:

 
好了,上面都是众所周知的,好,下面开始展示点有意思的。
大家看下下面2行简单的查询语句:
document.querySelectorAll("#my-id div div");
document.querySelector("#my-id").querySelectorAll("div div");
 提问:上面两个语句返回的NodeList的内容是否是一样的?
给大家1分钟的时间思考下。
//zxx: 假设1分钟已经过去了
好了,答案是:不一样的。估计不少人跟我一样,会认为是一样的。
实际上:
document.querySelectorAll("#my-id div div").length === 1;
document.querySelector("#my-id").querySelectorAll("div div").length === 3;
大家如果有疑问,可以在控制台测试下,下图就是我自己测试的结果:

为啥会这样?
第一个符合我们的理解,不解释。那下一个语句,为何返回的NodeList长度是3呢?
首先,遍历该NodeList会发现,查询的三个dom元素为:div.lonely, div.outer, div.inner.
奇怪,奇怪,怎么会是3个呢?
jQuery中有个find()方法,大家很可能受到这个方法影响,导致出现了一些认知的问题:
$("#my-id").find("div div").length === 1;
如果使用find方法,则是1个匹配;由于结构和作用类似,我们很自然疑问原生的querySelectorAll也是这个套路。真是太错特错!!
要解释,为何NodeList长度是3,只要一句话就可以了,我特意加粗标红:
CSS选择器是独立于整个页面的!
什么意思呢?比如说你在页面很深的一个DOM里面写上:
<style>
div div { }
</style>
整个网页,包括父级,只要是满足div div父子关系的元素,全部会被选中,对吧,这个大家应该都清楚的。
这里的querySelectorAll里面的选择器也同样是这也全局特性。document.querySelector("#my-id").querySelectorAll("div div")翻译成白话文就是:查询#my-id的子元素,同时满足整个页面下div div选择器条件的DOM元素们。
我们页面往上滚动看看原始的HTML结构,会发现,在全局视野下,div.lonely, div.outer, div.inner全部都满足div div这个选择器条件,于是,最终返回的长度为3.
二、:scope与区域选择限制
其实,要想querySelectorAll后面选择器不受全局影响,也是有办法的,就是使用目前还处于实验阶段的:scope伪类,其作用就是让CSS是在某一范围内使用。此伪类在CSS中使用是大头,但是也可以在querySelectorAll语句中使用:
document.querySelector("#my-id").querySelectorAll(":scope div div");
兼容性如下:
我写此文时候是15年11月初,目前基本上就FireFox浏览器支持,我估计,以后,会支持越来越多的。为什么呢?
因为Web Components需要它,可以实现真正独立封装,不会受外界影响的HTML组件。
关于:scope目前支持尚浅,时机未到,我就没必要乱展开了,点到为止。
三、结语还是要的
参考文章:querySelectorAll from an element probably doesn’t do what you think it does
感谢阅读,欢迎纠错,欢迎交流!
DOM元素querySelectorAll可能让你意外的特性表现的更多相关文章
- HTML5中DOM元素的querySelector/querySelectorAll的工作机制
		
在HTML5中,提供了强大的DOM元素选择API querySelector/querySelectorAll,允许使用JavaScript代码来完成类似CSS选择器的DOM元素选择功能.通常情况下, ...
 - 【面试必备】javascript操作DOM元素
		
前言 时间过的真快,不知不觉就到年底了.问问自己,这一年你对自己的工作满意吗? 评价标准是什么呢?当然是马云的那两条准则了:钱给到了吗?干的爽吗?如果答案都是no,那么,你准备好跳槽了吗? 为了应对年 ...
 - HTML DOM 元素对象
		
HTML DOM 元素对象 HTML DOM 节点 在 HTML DOM (Document Object Model) 中, 每个东西都是 节点 : 文档本身就是一个文档对象 所有 HTML 元素都 ...
 - JS1 js获取dom元素方法
		
js获取dom元素方法 1.通过ID选取元素(getElementById) 1)使用方法:document.getElementById("domId") 其 ...
 - riot.js教程【三】访问DOM元素、使用jquery、mount输入参数、riotjs标签的生命周期
		
前文回顾 riot.js教程[二]组件撰写准则.预处理器.标签样式和装配方法 riot.js教程[一]简介 访问DOM元素 你可以通过this.refs对象访问dom元素 而且还有大量的属性简写方式可 ...
 - Html开发中document.getElementByTagName无法找到所有DOM元素的问题解决方法
		
let eleList = document.querySelectorAll('li') for (let i = 0; i < eleList.length; i++) { // 遍历操作 ...
 - JS----获取DOM元素的方法(8种)
		
什么是HTML DOM 文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展置标语言的标准编程接口.简单理解就是HTML DOM 是关于如何获取.修改.添加或删除 ...
 - JavaScript DOM 元素属性 状态属性
		
JavaScript DOM 元素属性 状态属性 版权声明:未经允许,严禁转载! 元素的属性 核心 DOM 为我们提供了操作元素标准属性的统一 API. 所有属性节点都储存在元素的 attribute ...
 - JS选取DOM元素的方法
		
摘自JavaScript权威指南(jQuery根据样式选择器查找元素的终极方式是 先用getElementsByTagName(*)获取所有DOM元素,然后根据样式选择器对所有DOM元素进行筛选) 今 ...
 
随机推荐
- Scala的几个小tips
			
1. Main方法只能写在object而不是class里 2. Unit test只能针对class或者trait,不能给object做,解决方法,把object里面要测的方法拿出来放到trait里, ...
 - JavaScript的学习4
			
一.Array对象 ArrayObject.reverse() 将数组进行翻转 ArrayObject.shift() 删除数组中的第一个元素并将其返回 ArrayObject.unshi ...
 - js 取得 Unix时间戳(Unix timestamp)
			
js 取得 Unix时间戳 Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间19 ...
 - 如何让NGUI的对象在3D模型之上
			
假设场景中有两台摄像机, 一台是NGUI的摄像机, 另外一台是投影摄像机. 投影摄像机看的是3D模型, Depth比NGUI的摄像机要大, Clear Flags设置的是Depth only. 现在想 ...
 - [DFNews] Elcomsoft 发布EPPB 2.00.233
			
Elcomsoft Phone Password Breaker 是俄罗斯Elcomsoft公司推出的手机取证工具,能够针对黑莓.苹果等手机的备份文件进行多种方式破解,支持远程获取iCloud数据. ...
 - 培训第四天-----jdbc连接oracle
			
oracle链接数据库并向tableone插入中一条数据 package com.zjw.db; import java.sql.Connection; import java.sql.DriverM ...
 - cocos2dx day 2 - Sprites
			
1.Sprite 对sprite设置anchor point,对应的位置 // DEFAULT anchor point for all Sprites mySprite->setAnchorP ...
 - Solaris 自动挂载
			
修改文件:vim /etc/vfstab添加命令:/dev/dsk/c2t0d0p0:1 - /media/PARTITION1 pcfs ...
 - setContentView R can not be resovled
			
原因:gen包下没有自动生成R.java的资源文件 解决办法:再次新建android application project,默认Theme为Holo Light With Dark Action B ...
 - 开发android App干坏事(一)
			
最近都是在搞java,android的知识,前两天生日朋友和我聊到,有一个认识的人通过反编译android程序往里面插入广告积分墙赚了很大一笔钱,很短时间内赚了几十万,(为毛感觉这已经是扯淡篇了,转入 ...