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上。