在javascript將NodeList做爲Array數組處理的方法

轉自:http://www.jb51.net/article/24182.htmjavascript

var anchors = document.getElementsByTagName("a");
for (i = 0; i < anchors.length; i++) {
var ele=anchors[i];//取某一個元素
//some code here
} 

上面的代碼表示獲取文檔中的全部連接元素,而後遍歷作一些事情。
也許你會問,經過這種方法獲取的這一組dom元素不就是一個數組嗎?你看,你都 能夠直接獲取它的length屬性,還能夠根據索引取到對應的單獨元素,根據大牛的著名鴨子理論,它像鴨子同樣行走(有length屬性),像鴨子同樣叫 喚(根據索引取值),那麼它就是一隻鴨子。結論不言自明瞭吧?
若是,你已經對javascript稍微有過深刻的瞭解,有length屬性,可 以索引取值,必定是數組嗎,好像arguments也會這麼一手吧,arguments是數組?雖然在實際開發的時候,咱們把它當作普通數組來操 做,length和for循環使用的不亦樂乎,並且並不見得會出錯。
可是,它真的不是數組(Array),而是NodeList。NodeList不是數組。
What a surprise,right?html

一、NodeList爲何不是數組?

驗證NodeList是否是數組,最直接的方法也許是試一下Array專有的push和pop大法:java

var anchors = document.getElementsByTagName("a");
var newEle = document.createElement("a");//新建一個a元素
anchors.push(newEle);//push
var element= anchors.pop();//pop

您能夠本身測試一下,上面的代碼不論是push仍是pop方法,無一例外的會提示你沒有push或者pop方法。還有疑問嗎?這樣就結束了嗎?這種片面的 測試反倒使樓豬沒法高枕無憂問心無愧了。咱們徹底能夠像證實arguments不是數組同樣,也用一樣的方法證實NodeList不是數組。看下面的代碼 吧:node

Array.prototype.testNodeList = "test nodelist"; //數組添加原型屬性
function funcNodeList() {
var links = document.getElementsByTagName("a");
alert(links.testNodeList);
}
function test() {
alert(new Array().testNodeList); //test nodelist
funcNodeList(); //#ff0000? what the hell is that?
}
test(); //測試一下 

經過上面的分析,咱們能夠確定NodeList不是數組(Array)了。那麼如何按照咱們操做集合的習慣操做NodeList呢?

二、像操做Array同樣操做NodeList

既然NodeList有length,能夠for循環索引取值,轉換成數組還不是垂手可得?哈哈,最直接的思路是這樣的:編程

var arr = new Array();
var anchors = document.getElementsByTagName("a")
for (var i = 0; i < anchors.length; i++) {
var ele = anchors[i];
arr.push(ele); //arr就是咱們要的數組
} 

簡明扼要說明一下吧:先new一個Array,遍歷NodeList,而後將每個單獨的元素push到數組變量裏,最後操做數組變量,over。有沒有智商受辱的感受?
上面不是跟您開玩笑,由於下面是樓豬在網上google到的,兩行代碼就能夠將NodeList轉換成Array來使用了:c#

var anchors = document.getElementsByTagName("a");
var arr = Array.prototype.slice.call(anchors); //非ie瀏覽器正常 

可是,最最遺憾的事情發生了:上面的代碼在萬惡的IE下不能正常工做,IE會給你提示: 缺乏 JScript 對象。
你可能會對上面的一大段 分析不屑一顧,認爲沒有必要將NodeList轉換成Array來操做。其實,樓豬我的也認爲,無論在哪一種編程語言裏,類型轉換都是很是不明智的行爲。最 常見的好比c#裏的裝箱和拆箱,數值型數據轉換,有性能問題,一不當心還會觸雷。可是爲何樓豬單獨要把NodeList當作Array來處理呢?由於動 態改變NodeList的時候,直接操做NodeList極可能會誤闖禁區而渾然不覺。下面舉個例子:
(1)、html文檔片斷 數組

<div id="divAnchor">
<a href="http://www.cnblogs.com/jeffwongishandsome/">link test</a>
</div> 

(2)、javascript測試代碼瀏覽器

var anchors = document.getElementsByTagName("a");
for (i = 0; i < anchors.length; i++) {
var ele= document.createElement("a");
ele.setAttribute("href", "http://www.cnblogs.com/jeffwongishandsome/");
ele.appendChild(document.createTextNode("new link test"));
document.getElementById("divAnchor").appendChild(ele); //div附加一個新連接
} 

在文檔加載結束後,執行上面的腳本。咱們的本意是在div內,已經存在的a元素後再附加一個a元素。可是,您能夠運行一下,瀏覽器crash掉了吧?樓豬 這裏IE直接掛掉,FF提示腳本正忙,是否中止腳本運行,點擊中止後,頁面內已經生成了n多個a連接。其實咱們能夠大膽分析出緣由來:for循環 NodeList(前提:for循環內部添加了新的元素使nodelist長度發生了變化。感謝陳童鞋超羣的建議),它的length會不斷變化上升,循 環循環再循環,最後成了個死循環。而用下面的代碼,和咱們預期的效果是同樣同樣的:安全

var links = document.getElementsByTagName("a");
var anchors = null; //數組
try {
anchors = Array.prototype.slice.call(links);
}
catch (e) { //兼容ie
anchors = new Array();
for (var i = 0; i < links.length; i++) {
anchors.push(links[i]);
}
}
for (i = 0; i < anchors.length; i++) { //數組循環 安全多了
var ele = document.createElement("a");
ele.setAttribute("href", "http://www.cnblogs.com/jeffwongishandsome/");
ele.appendChild(document.createTextNode("new link test"));
document.getElementById("divAnchor").appendChild(ele); //div附加一個新連接
} 

那麼你可能會問,不轉換不行嗎?沒有那麼死板,固然是能夠的,只要對咱們平時熟悉的編碼習慣稍微動點小手術就能夠了:app

var anchors = document.getElementsByTagName("a");
var len = anchors.length; //定義一個變量
for (i = 0; i < len; i++) { //對局部變量len進行循環
var ele = document.createElement("a");
ele.setAttribute("href", "http://www.cnblogs.com/jeffwongishandsome/");
ele.appendChild(document.createTextNode("new link test"));
document.getElementById("divAnchor").appendChild(ele); //div附加一個新連接
} 

轉自:http://www.jb51.net/article/24182.htm

相關文章
相關標籤/搜索