W3C在07年的Selectors API中新增了两个API —— querySelector和querySelectorAll。这两个API在文档中的描述以下:html
partial interface Document { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); }; partial interface DocumentFragment { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); }; partial interface Element { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); };
从接口定义中就能够看出,Document,DocumentFragment和Element都支持querySelector和querySelectorAll。其中querySelector返回的是单个元素,而querySelectorAll返回的是匹配到的全部DOM组成的NodeList。c++
构想一下下面的HTML结构:api
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div id="container" class="container"> <div class="name">Lever</div> <div class="content"> <div>Hello World!</div> </div> </div> </body> </html>
如今试着用querySelector和querySelectorAll来处理DOM。浏览器
const container = document.querySelector("#container") const name1 = container.querySelector(".name").innerText const name2 = document.querySelector("#container > .name").innerText console.log(name1, name2) // Lever Lever
这里分别在"#container"这个元素和document上调用了querySelector,能够看出,使用在Element上的querySelector是被限制在该Element的范围内的,而在document上调用的querySelector则会在全局中寻找符合条件的元素。lua
const name3 = container.querySelector(".container > .name").innerText
如今猜猜,name3会输出什么。若是常用jQuery的话,很容易认为这样的选择器不会匹配到任何DOM,由于在“#container”的子元素中没有匹配的DOM。但结果实际上是选择器正确的拿到了咱们要找的DOM,name3的值为“Lever”。code
不要怀疑,这不是浏览器的bug,规范中是这样描述的:htm
Even though the method is invoked on an element, selectors are still evaluated in the context of the entire document. In the following example, the method will still match the div element's child p element, even though the body element is not a descendant of the div element itself.接口
var div = document.getElementById("bar"); var p = div.querySelector("body p");
按照规范的意思,在Element下的querySelector一样会在整个document下寻找符合条件的选择器,而后才会将结果中属于Element子树的DOM截取出来。ip
这样看来,也就能解释为何获取name3的选择器仍然会起做用了。utf-8
还须要注意的是,经过querySelectorAll选取出来的NodeList是静态的,所以任何对DOM的增删改的操做,不会影响到已经查询出来的NodeList的结果。
与本文的相关代码都放到了JSBin上。