摘要:也就是說,對底層文檔結構的修改會動態地反映到相關的結合以及中。動態對象通過在緩存中注冊它的存在并創建。在中執行靜態查詢的前期成本相比要顯著提高很多倍。
ps:了解這個知識點的原因
前兩天我在重溫js dom編程的時候,看到了獲取dom元素這一章,然后看到了getElementsByTagName()和getElementsByClassName(),之后又了解到了現代瀏覽器新出的一個DOM API--querySelectorAll().以我的性格,看到這些方法之后我肯定是想了解一下它們的不同點啦,所以我就翻閱資料,就看到了stackoverflow上面的一個問題
var temp = document.querySelectorAll(".class"); for (var i=0, max=temp.length; i運行上述這兩段代碼,假如獲取到的temp的長度都為3,那么第一段代碼能將三個元素的className全部更改為new_class",而第二段代碼只能講第一個元素和第三個元素的className更改為"new_class".這里面的原因就是動態nodelist和靜態nodelist的區別。
說說NodeList,HTMLCollection以及NamedNodeMap
然后我又翻閱資料查找什么是動態nodelist,什么是靜態nodelist。于是乎,就有了下面的長篇大論。在不同版本的瀏覽器中,如果調用獲取多元素的DOM方法(getElement...()),有的會得到NodeList(多為舊瀏覽器),有的會得到HTMLCollection(多為新瀏覽器)。使用Node Interface的方法,如childNodes,得到的通常是NodeList,而使用其他Interface的方法,又有可能得到HTMLCollection。而NamedNodeMap又和前面兩者返回的東西類型也不相同,所以有必要了解一下這三者的區別。
1. 三者的相同點
1.1 三者都具有length屬性
1.2 三者都有item()方法
1.3 三個集合都是"動態的",如果對NodeList和HTMLCollection中的元素進行操作都會直接反映到DOM中,因此如果一次性直接在集合中進行DOM操作的話,開銷非常大。(這會在講解動態的時候詳細解釋)
2. 三者的不同點
2.1 nodeList里面包含了所有的節點類型,比如元素節點,文本節點等
2.2 HTMLCollection里面只包含元素節點
This is Some Text
上面這段代碼,如果作為NodeList返回,那么瀏覽器最多會給這個列表5個元素
1.一個
和注釋間的斷行和空格(或tab)作為text node(沒錯,標簽之間的空白符號也可以被解析為text node之間的斷行和空格(或tab)作為text node2.注釋作為comment node
3.注釋和
之間的斷行和空格(或tab)作為text node,p作為element
4.
和但是如果是作為HTMLCollection返回的話,那么就一個
元素這么簡單
2.3 NamedNodeMap里面包含了"Attribute"的集合,例如id,title,name等,集合中的每一個元素都是attr類型。
2.4 三個集合所提供的方法也不相同,例如HTMLCollection中提供了namedItem(),而其它兩個集合就沒有提供這個方法
擴展點:
item和namedItem都可以通過[]的縮寫進行調用,有的瀏覽器還支持用()的縮寫進行調用(也就是可以list[index],list[key]或者list(index),list(key)),以及直接用dot notation調用namedItem(比如list.key)
IE8及以下版本瀏覽器中,注釋屬于HTMLCommentElement,算作Element,因此會出現在HTMLCollection里
我們可以用alert/console.log(document.getElement...)打印出來看下返回的是什么類型的集合,下面這個鏈接中講的也算詳細,可以參考下:http://www.jb51.net/article/2...
ps:以上知識點參考鏈接:
http://www.cnblogs.com/joyeec...,
說了這么多,那么到底什么是動態NodeList?什么是靜態NodeList呢?它們之間有什么區別? 動態NodeList
http://stackoverflow.com/ques...,
http://stackoverflow.com/ques...上面我們說到NodeList,HTMLCollection以及NamedNodeMap都是動態的。也就是說,對底層文檔結構的修改會動態地反映到相關的結合NodeList,HTMLCollection以及NamedNodeMap中。例如:如果先獲取了某個元素的子元素的動態集合NodeList對象,然后又在其他地方對這個元素進行操作(添加,修改,刪除子元素等操作),這些更改將自動反射到NodeList中,不需要手動進行操作。
因為getElementsByTagName(所有getElement...方法都會返回動態NodeList)方法返回的是一個動態集合,所以只要document發生變化,就會自動更新對應的元素。因此,下面的代碼是一個死循環:
var divs = document.getElementsByTagName("div"); var i=0; while(i < divs.length){ document.body.appendChild(document.createElement("div")); i++; }死循環的原因是每次循環都會重新計算divs.length.每次迭代都會添加一個新的
,所以每次i++,對應的divs.length也在增加,所以i永遠比divs.length小,循環終止條件也就永遠不會觸發。解決上述代碼死循環的辦法可以是用一個變量存儲divs.length或者改用querySelectorAll():
var divs = document.getElementsByTagName("div"); var i=0,len = divs.length; while(i < len){ document.body.appendChild(document.createElement("div")); i++; }你可能會覺得這種動態集合是個壞主意, 但通過動態集合可以保證某些使用非常普遍的對象在各種情況下都是同一個,而且動態NodeList比靜態NodeList快很多很多(下面解釋原因)
靜態NodeListquerySelectorAll()和querySelector()方法返回的是一個靜態的NodeList,所謂靜態NodeList就是對底層document的更改不會影響到返回的這個NodeList對象.此時返回的NodeList只是querySelectorAll()方法被調用時的文檔狀態的快照。所以下面的代碼不會是死循環:
var divs = document.querySelectorAll("div"); var i=0; while(i < divs.length){ document.body.appendChild(document.createElement("div")); i++; }在這種情況下沒有死循環, divs.length的值永遠不會改變, 所以只要不滿足循環條件, 就退出循環。
為什么動態NodeList更快呢?我在某篇文章中看到有人測試了一下getElementsByTagName()比querySelectorAll()快好多倍。
原因是:動態NodeList對象在瀏覽器中可以更快地被創建并返回,因為他們不需要預先獲取所有的信息,而靜態NodeList對象從一開始就需要取得并封裝所有相關的數據。兩種對象類型的創建方式是完全不同的。
DynamicNodeList(動態NodeList)對象通過在cache緩存中注冊它的存在并創建。從本質上講,創建一個新的DynamicNodeList是非常輕量級的,因為不需要做任何的前期工作。每次訪問 DynamicNodeList 時, 必須查詢 document 的變化, length 屬性 以及 item() 方法證明了這一點
相比之下,StaticNodeList對象實例由另外一個文件創建,然后循環填充所有的數據。在document中執行靜態查詢的前期成本相比DynamicNodeList要顯著提高很多倍。
如果真正的查看WebKit的源碼,你會發現他為 querySelectorAll() 明確地 創建一個返回對象 ,在其中又使用一個循環來獲取每一個結果,并創建最終返回的一個 NodeList.
結論getElementsTagName()方法速度比querySelectorAll()方法快的根本原因在于動態NodeList和靜態NodeList對象不同。在獲取NodeList時不需要執行很多前期處理操作的動態列表總比獲取返回之前完成各種處理的靜態NodeList要快很多。哪個方法更好用還是看你的需求。如果不需要獲取快照,就使用getElement...方法;如果需要靜態快照結果,或者需要使用更復雜的css查詢,則可以考慮querySelectAll()方法
對開頭題目講解/**通過querySelectorAll()獲取到的元素集合temp是靜態的快照,所以temp長度不會變化,max始終為3,所以通過for循環3個對應元素的class名字都被改成"new_class"**/ var temp = document.querySelectorAll(".class"); for (var i=0, max=temp.length; i參考資料鏈接:
https://github.com/cncounter/...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88196.html
摘要:唯一要注意的是返回的雖然是,但是實際上是元素集合,并且是靜態的其他接口返回的和都是的。與相同的是它也是一個動態的集合,與不同的是,中保存的是一組無序的屬性節點的集合。及以下版本瀏覽器中,注釋屬于算作因此會出現在里。而且是元素的集合。 NodeList v.s. HTMLCollection 主要有兩個方面不一樣1.包含節點的類型2.使用方法 1.包含節點的類型不同(重要) (1)Nod...
摘要:唯一要注意的是返回的雖然是,但是實際上是元素集合,并且是靜態的其他接口返回的和都是的。與相同的是它也是一個動態的集合,與不同的是,中保存的是一組無序的屬性節點的集合。及以下版本瀏覽器中,注釋屬于算作因此會出現在里。而且是元素的集合。 NodeList v.s. HTMLCollection 主要有兩個方面不一樣1.包含節點的類型2.使用方法 1.包含節點的類型不同(重要) (1)Nod...
摘要:展開的屬性后發現,繼承于一個對象,而這個對象又繼承于對象。這證實了我們對的猜想。是比較新的模型,相比更加完善,不光有元素,還有節點和。關于,和的關系,就是長得像,有個別相似的功能,但是是完全不一樣的東西。 Array,NodeList, HTMLCollection這三個概念和它們之間的關系有很多做了幾年前端的同學都搞不清楚,經常遇到但是又感覺很陌生,剪不斷理還亂的感覺。今天咱們就來理...
摘要:展開的屬性后發現,繼承于一個對象,而這個對象又繼承于對象。這證實了我們對的猜想。是比較新的模型,相比更加完善,不光有元素,還有節點和。關于,和的關系,就是長得像,有個別相似的功能,但是是完全不一樣的東西。 Array,NodeList, HTMLCollection這三個概念和它們之間的關系有很多做了幾年前端的同學都搞不清楚,經常遇到但是又感覺很陌生,剪不斷理還亂的感覺。今天咱們就來理...
閱讀 2020·2021-10-09 09:41
閱讀 1596·2021-09-28 09:36
閱讀 1100·2021-09-26 09:55
閱讀 1285·2021-09-10 11:17
閱讀 1141·2021-09-02 09:56
閱讀 2755·2019-08-30 12:58
閱讀 2927·2019-08-29 13:03
閱讀 1847·2019-08-26 13:40