標籤:枚舉 注意事項 turn app cto for 元素 sel attr
NodeList
NodeList執行個體對象是一個類數組對象,它的成員是節點對象,包括childNodes和querySelectorAll()方法傳回值
<div id="test"></div><script>console.log(test.childNodes);//[]//IE7-瀏覽器並未定義NodeList對象,會報錯,其他瀏覽器返回trueconsole.log(test.childNodes instanceof NodeList)</script>
<div id="test"></div><script>console.log(document.querySelectorAll(‘div‘));//[div#test]//IE8-瀏覽器不支援querySelectorAll()方法,返回false,其他瀏覽器返回trueconsole.log(document.querySelectorAll(‘div‘) instanceof NodeList)</script>
動態集合是指DOM結構的變化能夠自動反映到所儲存的對象中
<div id="test"></div><script>var childN = test.childNodes;console.log(childN);//[]test.appendChild(document.createElement(‘div‘));console.log(childN);//[div]</script>
靜態
[注意]NodeList並不都是動態集合,其中querySelectorAll()傳回值就是靜態集合NodeStaticList
<div id="test"></div><script>var seles = test.querySelectorAll(‘div‘);console.log(seles);//[]test.appendChild(document.createElement(‘div‘));console.log(seles);//[]console.log(test.querySelectorAll(‘div‘));//[div]</script>
數組
由於NodeList是類數組對象,並不是真正的數組對象,可以使用slice()方法將其變成真正的數組
<div id="test"></div><script>var childN = test.childNodes;console.log(childN instanceof Array);//falsevar childNew = Array.prototype.slice.call(childN);console.log(childNew instanceof Array);//true</script>
但是,由於IE8-瀏覽器將NodeList實現為一個COM對象,不能使用Array.prototype.slice()方法,必須手動枚舉所有成員
<div id="test"></div><script>var childN = test.childNodes;console.log(childN instanceof Array);//falsefunction convertToArray(nodes){ var array = null; try{ array = Array.prototype.slice.call(nodes) }catch(ex){ array = []; var len = nodes.length; for(var i = 0; i < len; i++){ array.push(nodes[i]); } } return array;}var childNew = convertToArray(childN);console.log(childNew instanceof Array);//true</script>
HTMLCollection
HTMLCollection對象與NodeList對象類似,也是節點的集合,返回一個類數組對象。但二者有不同之處
NodeList集合主要是Node節點的集合,而HTMLCollection集合主要是Element元素節點的集合。Node節點共有12種,Element元素節點只是其中一種。關於12種節點類型的詳細資料移步至此
HTMLCollection集合包括getElementsByTagName()、getElementsByClassName()、getElementsByName()等方法的傳回值,以及children、document.links、document.forms等元素集合
<div id="test"></div><script>var childN = test.children;//IE7-瀏覽器並未定義HTMLCollection對象,會報錯,其他瀏覽器返回trueconsole.log(childN instanceof HTMLCollection);var tags =test.getElementsByTagName(‘div‘);//IE7-瀏覽器並未定義HTMLCollection對象,會報錯,其他瀏覽器返回trueconsole.log(tags instanceof HTMLCollection);</script>
動態
與NodeList對象不同,所有的HTMLCollection對象都是動態
<div id="test"></div><script>var childN = test.children;var tags =test.getElementsByTagName(‘div‘);console.log(childN,tags);//[]、[]test.innerHTML = ‘<div></div>‘;console.log(childN,tags);//[div]、[div]</script>
[注意]與NodeList對象類似,要想變成真正的數組Array對象,需要使用slice()方法,在IE8-瀏覽器中,則必須手動枚舉所有成員
NamedNodeMap
可能一些人沒有聽過NamedNodeMap對象,該對象的常見執行個體對象是attributes屬性
<div id="test"></div><script>var attrs = test.attributes;console.log(attrs instanceof NamedNodeMap);//true</script>
動態
該對象也是一個動態集合
<div id="test"></div><script>var attrs = test.attributes;console.log(attrs);//NamedNodeMap {0: id, length: 1}test.setAttribute(‘title‘,‘123‘);console.log(attrs);//NamedNodeMap {0: id, 1: title, length: 2}</script>
注意事項
動態集合是個很實用的概念,但在使用迴圈時一定要千萬小心。可能會因為忽略集合的動態性,造成死迴圈
var divs = document.getElementsByTagName("div");for(var i = 0 ; i < divs.length; i++){ document.body.appendChild(document.createElement("div"));}
在上面代碼中,由於divs是一個HTMLElement集合,divs.length會隨著appendChild()方法,而一直增加,於是變成一個死迴圈
為了避免此情況,一般地,可以寫為下面形式
var divs = document.getElementsByTagName("div");for(var i = 0,len = divs.length; i < len; i++){ document.body.appendChild(document.createElement("div"));}
一般地,要盡量減少訪問NodeList、HTMLCollection、NamedNodeMap的次數。因為每次訪問它們,都會運行一次基於文檔的查詢。所以,可以考慮將它們的值緩衝起來
最後
NodeList是節點的集合,HTMLCollection是元素節點的集合,NamedNodeMap是特性節點的集合,它們都是類數組對象
對了,還有一個更經典的類數組對象——函數內部的arguments,它也具有動態性
PS:原文https://www.cnblogs.com/xiaohuochai/p/5827389.html
深入理解javascript中的動態集合——NodeList、HTMLCollection和NamedNodeMap