[label][转载][JavaSript]querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?
?轉載出處: http://www.zhihu.com/question/24702250
querySelectorAll?相比下面這些方法有什么區別?
- getElementsByTagName
- getElementsByClassName
- getElementsByName
1. W3C 標準
querySelectorAll 屬于 W3C 中的 Selectors API 規范 [1]。而 getElementsBy 系列則屬于 W3C 的 DOM 規范 [2]。
2. 瀏覽器兼容
querySelectorAll 已被 IE 8+、FF 3.5+、Safari 3.1+、Chrome 和 Opera 10+ 良好支持 。
getElementsBy 系列,以最遲添加到規范中的 getElementsByClassName 為例,IE 9+、FF 3 +、Safari 3.1+、Chrome 和 Opera 9+ 都已經支持該方法了。
3. 接收參數
querySelectorAll 方法接收的參數是一個 CSS 選擇符。而 getElementsBy 系列接收的參數只能是單一的className、tagName 和 name。代碼如下 [3]:
需要注意的是,querySelectorAll 所接收的參數是必須嚴格符合 CSS 選擇符規范的。所以下面這種寫法,將會拋出異常。代碼如下 [4]:
try {var e1 = document.getElementsByClassName('1a2b3c'); var e2 = document.querySelectorAll('.1a2b3c'); } catch (e) { console.error(e.message); } console.log(e1 && e1[0].className); console.log(e2 && e2[0].className);(CSS 選擇器中的元素名,類和 ID 均不能以數字為開頭。)
4. 返回值
大部分人都知道,querySelectorAll 返回的是一個 Static Node List,而 getElementsBy 系列的返回的是一個 Live Node List。
看看下面這個經典的例子 [5]:
因為 Demo 2 中的 lis 是一個動態的 Node List, 每一次調用 lis 都會重新對文檔進行查詢,導致無限循環的問題。
而 Demo 1 中的 lis 是一個靜態的 Node List,是一個 li 集合的快照,對文檔的任何操作都不會對其產生影響。
但為什么要這樣設計呢?
其實,在 W3C 規范中對 querySelectorAll 方法有明確規定 [6]:
那什么是 NodeList 呢?
W3C 中是這樣說明的 [7]:
所以,NodeList 本質上是一個動態的 Node 集合,只是規范中對 querySelectorAll 有明確要求,規定其必須返回一個靜態的 NodeList 對象。
我們再看看在 Chrome 上面是個什么樣的情況:
這里又多了一個 HTMLCollection 對象出來,那 HTMLCollection 又是什么?
HTMLCollection 在 W3C 的定義如下 [8]:
Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.
實際上,HTMLCollection 和 NodeList 十分相似,都是一個動態的元素集合,每次訪問都需要重新對文檔進行查詢。兩者的本質上差別在于,HTMLCollection 是屬于?Document Object Model HTML?規范,而 NodeList 屬于?Document Object Model Core?規范。
這樣說有點難理解,看看下面的例子會比較好理解 [9]:
NodeList 對象會包含文檔中的所有節點,如 Element、Text 和 Comment 等。
HTMLCollection 對象只會包含文檔中的 Element 節點。
另外,HTMLCollection 對象比 NodeList 對象 多提供了一個 namedItem 方法。
所以在現代瀏覽器中,querySelectorAll 的返回值是一個靜態的 NodeList 對象,而 getElementsBy 系列的返回值實際上是一個 HTMLCollection 對象 。
[1]?Selectors API Level 2
[2]?Document Object Model Core
[3]?http://jsbin.com/cuduyigi/1/edit?html,js,console
[4]?http://jsbin.com/mabefihi/1/watch?html,js,console
[5]?
Demo 1:?http://jsbin.com/daduziba/1/watch?html,js,output
Demo 2:?http://jsbin.com/xuvodipo/1/watch?html,js,output
[6]?Selectors API Level 2
[7]?Document Object Model Core
[8]?Document Object Model HTML
[9]?http://jsbin.com/qijivove/1/watch?html,js,console
?
getElementById / querySelector 這兩個獲取到的都是dom節點,結果沒有區別。
getElement* 的實時性體現在返回集合的時候,我們知道getElementsBy*和querySelectorAll返回的都是一個節點集合,類似于數組,兩種方法的區別就在于這個集合會不會自動更新。
另外,getElementById這個只能用在document上,因為正常情況下id是唯一的。
?
上面說了很多querySelectorAll和getElementsBy實現和原理上面的區別,我這里拿數據說話,看看兩者在性能上的區別。
所有測試來源于http://jsperf.com/getelementsby-vs-queryselectorall/7,有興趣的朋友可以自己去試試。
- 硬件環境: Core i5-3570 3.40GHz, Win7 64bit
- 數據格式:[ Ops/Sec] method
Ops/Sec是指每秒執行操作的次數,越高越好。
- 瀏覽器1: Chrome 37.0.2062.68 32-bit
點評:?
getElementBy系列的執行速度基本都是querySelectorAll的100+倍
- 瀏覽器2: Firefox 31.0 32-bit
點評:?
Firefox上getElementsByTagName和getElementsByClassName比Chrome快了10倍,而其余四個則相差無幾,有高人能解析下原因么?
- 瀏覽器3: IE 11.0.9600
點評:?
IE比FF和Chrome慢的太多了。不過沒關系:速度不夠,情懷來湊嘛。
主要是選擇器的區別和是否實時的區別。
1.選擇器
- querySelector**
querySelector和querySelectorAll 是HTML5新引入的功能類似jQuery的選擇器。前者返回按文檔順序返回指定元素節點的子樹中匹配選擇器的第一個元素,沒有則返回null。后者返回按文檔順序返回指定元素節點的子樹中匹配選擇器的元素集合,如果沒有匹配返回空集合。以querySelectorAll為例說明。
querySelectorAll('selectors'),其中的selectors可以包含多個CSS選擇器,可以是類選擇器,也可以是ID選擇器,也可以是Tag類型選擇器,當然也可以是它們的混合。如
- getElementsBy***
getElementsBy***只能根據特定選擇器尋找。getElementById(id)選擇器內容是id名,返回擁有第一個這個id的對象引用。比如有一個
<div id="no1"><div>元素。可以用querySelector('#no1')或者getElementById('no1')獲取。getElementsByTagName的選擇器tagname,getElementsByName的選擇器是標簽的name屬性值,getElementsByClassName的選擇器是類名,都是直接寫名字,而不需要加#,.等標識符。
2.實時性
querySelector**返回的是非實時的。而getElementBy**返回的是實時的。
用以下的例子說明:
發現getElementBy的結果返回的實時的結果,而如果用querySelector,結果還是原來的結構返回結果。
轉載于:https://www.cnblogs.com/shuman/p/3972910.html
總結
以上是生活随笔為你收集整理的[label][转载][JavaSript]querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Xcode 6 allows VECTO
- 下一篇: cmd编译运行Java文件详解