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