在javascript將NodeList作為Array數(shù)組處理的方法
更新時間:2010年07月09日 00:52:54 作者:
在Web前端編程中,我們通常會通過document.getElementsByTagName的方法取出一組相同標(biāo)簽的dom元素。
比如:
var anchors = document.getElementsByTagName("a");
for (i = 0; i < anchors.length; i++) {
var ele=anchors[i];//取某一個元素
//some code here
}
上面的代碼表示獲取文檔中的所有鏈接元素,然后遍歷做一些事情。
也許你會問,通過這種方法獲取的這一組dom元素不就是一個數(shù)組嗎?你看,你都可以直接獲取它的length屬性,還可以根據(jù)索引取到對應(yīng)的單獨(dú)元素,根據(jù)大牛的著名鴨子理論,它像鴨子一樣行走(有l(wèi)ength屬性),像鴨子一樣叫喚(根據(jù)索引取值),那么它就是一只鴨子。結(jié)論不言自明了吧?
如果,你已經(jīng)對javascript稍微有過深入的了解,有l(wèi)ength屬性,可以索引取值,一定是數(shù)組嗎,好像arguments也會這么一手吧,arguments是數(shù)組?雖然在實際開發(fā)的時候,我們把它當(dāng)做普通數(shù)組來操作,length和for循環(huán)使用的不亦樂乎,而且并不見得會出錯。
但是,它真的不是數(shù)組(Array),而是NodeList。NodeList不是數(shù)組。
What a surprise,right?
1、NodeList為什么不是數(shù)組?
驗證NodeList是不是數(shù)組,最直接的方法也許是試一下Array專有的push和pop大法:
var anchors = document.getElementsByTagName("a");
var newEle = document.createElement("a");//新建一個a元素
anchors.push(newEle);//push
var element= anchors.pop();//pop
您可以自己測試一下,上面的代碼不管是push還是pop方法,無一例外的會提示你沒有push或者pop方法。還有疑問嗎?這樣就結(jié)束了嗎?這種片面的測試反倒使樓豬無法高枕無憂心安理得了。我們完全可以像證明arguments不是數(shù)組一樣,也用同樣的方法證明NodeList不是數(shù)組。看下面的代碼吧:
Array.prototype.testNodeList = "test nodelist"; //數(shù)組添加原型屬性
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不是數(shù)組(Array)了。那么如何按照我們操作集合的習(xí)慣操作NodeList呢?
2、像操作Array一樣操作NodeList
既然NodeList有l(wèi)ength,可以for循環(huán)索引取值,轉(zhuǎn)換成數(shù)組還不是輕而易舉?哈哈,最直接的思路是這樣的:g
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就是我們要的數(shù)組
}
明扼要說明一下吧:先new一個Array,遍歷NodeList,然后將每一個單獨(dú)的元素push到數(shù)組變量里,最后操作數(shù)組變量,over。有沒有智商受辱的感覺?
上面不是跟您開玩笑,因為下面是樓豬在網(wǎng)上google到的,兩行代碼就可以將NodeList轉(zhuǎn)換成Array來使用了:
var anchors = document.getElementsByTagName("a");
var arr = Array.prototype.slice.call(anchors); //非ie瀏覽器正常
但是,最最遺憾的事情發(fā)生了:上面的代碼在萬惡的IE下不能正常工作,IE會給你提示: 缺少 JScript 對象。
你可能會對上面的一大段分析不屑一顧,認(rèn)為沒有必要將NodeList轉(zhuǎn)換成Array來操作。其實,樓豬個人也認(rèn)為,不管在哪種編程語言里,類型轉(zhuǎn)換都是非常不明智的行為。最常見的比如c#里的裝箱和拆箱,數(shù)值型數(shù)據(jù)轉(zhuǎn)換,有性能問題,一不小心還會觸雷。但是為什么樓豬單獨(dú)要把NodeList當(dāng)做Array來處理呢?因為動態(tài)改變NodeList的時候,直接操作NodeList很可能會誤闖禁區(qū)而渾然不覺。下面舉個例子:
(1)、html文檔片段
<div id="divAnchor">
<a >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附加一個新鏈接
}
在文檔加載結(jié)束后,執(zhí)行上面的腳本。我們的本意是在div內(nèi),已經(jīng)存在的a元素后再附加一個a元素。但是,您可以運(yùn)行一下,瀏覽器crash掉了吧?樓豬這里IE直接掛掉,F(xiàn)F提示腳本正忙,是否停止腳本運(yùn)行,點(diǎn)擊停止后,頁面內(nèi)已經(jīng)生成了n多個a鏈接。其實我們可以大膽分析出原因來:for循環(huán)NodeList(前提:for循環(huán)內(nèi)部添加了新的元素使nodelist長度發(fā)生了變化。感謝陳童鞋超群的建議),它的length會不斷變化上升,循環(huán)循環(huán)再循環(huán),最后成了個死循環(huán)。而用下面的代碼,和我們預(yù)期的效果是一樣一樣的:
var links = document.getElementsByTagName("a");
var anchors = null; //數(shù)組
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++) { //數(shù)組循環(huán) 安全多了
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附加一個新鏈接
}
那么你可能會問,不轉(zhuǎn)換不行嗎?沒有那么死板,當(dāng)然是可以的,只要對我們平時熟悉的編碼習(xí)慣稍微動點(diǎn)小手術(shù)就可以了:
var anchors = document.getElementsByTagName("a");
var len = anchors.length; //定義一個變量
for (i = 0; i < len; i++) { //對局部變量len進(jìn)行循環(huán)
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附加一個新鏈接
}
到這里,不管有無疑問,實際編程如何取舍,樓豬都要感謝您的閱讀了。期待指點(diǎn)。
者:Jeff Wong
復(fù)制代碼 代碼如下:
var anchors = document.getElementsByTagName("a");
for (i = 0; i < anchors.length; i++) {
var ele=anchors[i];//取某一個元素
//some code here
}
上面的代碼表示獲取文檔中的所有鏈接元素,然后遍歷做一些事情。
也許你會問,通過這種方法獲取的這一組dom元素不就是一個數(shù)組嗎?你看,你都可以直接獲取它的length屬性,還可以根據(jù)索引取到對應(yīng)的單獨(dú)元素,根據(jù)大牛的著名鴨子理論,它像鴨子一樣行走(有l(wèi)ength屬性),像鴨子一樣叫喚(根據(jù)索引取值),那么它就是一只鴨子。結(jié)論不言自明了吧?
如果,你已經(jīng)對javascript稍微有過深入的了解,有l(wèi)ength屬性,可以索引取值,一定是數(shù)組嗎,好像arguments也會這么一手吧,arguments是數(shù)組?雖然在實際開發(fā)的時候,我們把它當(dāng)做普通數(shù)組來操作,length和for循環(huán)使用的不亦樂乎,而且并不見得會出錯。
但是,它真的不是數(shù)組(Array),而是NodeList。NodeList不是數(shù)組。
What a surprise,right?
1、NodeList為什么不是數(shù)組?
驗證NodeList是不是數(shù)組,最直接的方法也許是試一下Array專有的push和pop大法:
復(fù)制代碼 代碼如下:
var anchors = document.getElementsByTagName("a");
var newEle = document.createElement("a");//新建一個a元素
anchors.push(newEle);//push
var element= anchors.pop();//pop
您可以自己測試一下,上面的代碼不管是push還是pop方法,無一例外的會提示你沒有push或者pop方法。還有疑問嗎?這樣就結(jié)束了嗎?這種片面的測試反倒使樓豬無法高枕無憂心安理得了。我們完全可以像證明arguments不是數(shù)組一樣,也用同樣的方法證明NodeList不是數(shù)組。看下面的代碼吧:
復(fù)制代碼 代碼如下:
Array.prototype.testNodeList = "test nodelist"; //數(shù)組添加原型屬性
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不是數(shù)組(Array)了。那么如何按照我們操作集合的習(xí)慣操作NodeList呢?
2、像操作Array一樣操作NodeList
既然NodeList有l(wèi)ength,可以for循環(huán)索引取值,轉(zhuǎn)換成數(shù)組還不是輕而易舉?哈哈,最直接的思路是這樣的:g
復(fù)制代碼 代碼如下:
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就是我們要的數(shù)組
}
明扼要說明一下吧:先new一個Array,遍歷NodeList,然后將每一個單獨(dú)的元素push到數(shù)組變量里,最后操作數(shù)組變量,over。有沒有智商受辱的感覺?
上面不是跟您開玩笑,因為下面是樓豬在網(wǎng)上google到的,兩行代碼就可以將NodeList轉(zhuǎn)換成Array來使用了:
復(fù)制代碼 代碼如下:
var anchors = document.getElementsByTagName("a");
var arr = Array.prototype.slice.call(anchors); //非ie瀏覽器正常
但是,最最遺憾的事情發(fā)生了:上面的代碼在萬惡的IE下不能正常工作,IE會給你提示: 缺少 JScript 對象。
你可能會對上面的一大段分析不屑一顧,認(rèn)為沒有必要將NodeList轉(zhuǎn)換成Array來操作。其實,樓豬個人也認(rèn)為,不管在哪種編程語言里,類型轉(zhuǎn)換都是非常不明智的行為。最常見的比如c#里的裝箱和拆箱,數(shù)值型數(shù)據(jù)轉(zhuǎn)換,有性能問題,一不小心還會觸雷。但是為什么樓豬單獨(dú)要把NodeList當(dāng)做Array來處理呢?因為動態(tài)改變NodeList的時候,直接操作NodeList很可能會誤闖禁區(qū)而渾然不覺。下面舉個例子:
(1)、html文檔片段
<div id="divAnchor">
<a >link test</a>
</div>
(2)、javascript測試代碼
復(fù)制代碼 代碼如下:
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附加一個新鏈接
}
在文檔加載結(jié)束后,執(zhí)行上面的腳本。我們的本意是在div內(nèi),已經(jīng)存在的a元素后再附加一個a元素。但是,您可以運(yùn)行一下,瀏覽器crash掉了吧?樓豬這里IE直接掛掉,F(xiàn)F提示腳本正忙,是否停止腳本運(yùn)行,點(diǎn)擊停止后,頁面內(nèi)已經(jīng)生成了n多個a鏈接。其實我們可以大膽分析出原因來:for循環(huán)NodeList(前提:for循環(huán)內(nèi)部添加了新的元素使nodelist長度發(fā)生了變化。感謝陳童鞋超群的建議),它的length會不斷變化上升,循環(huán)循環(huán)再循環(huán),最后成了個死循環(huán)。而用下面的代碼,和我們預(yù)期的效果是一樣一樣的:
復(fù)制代碼 代碼如下:
var links = document.getElementsByTagName("a");
var anchors = null; //數(shù)組
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++) { //數(shù)組循環(huán) 安全多了
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附加一個新鏈接
}
那么你可能會問,不轉(zhuǎn)換不行嗎?沒有那么死板,當(dāng)然是可以的,只要對我們平時熟悉的編碼習(xí)慣稍微動點(diǎn)小手術(shù)就可以了:
復(fù)制代碼 代碼如下:
var anchors = document.getElementsByTagName("a");
var len = anchors.length; //定義一個變量
for (i = 0; i < len; i++) { //對局部變量len進(jìn)行循環(huán)
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附加一個新鏈接
}
到這里,不管有無疑問,實際編程如何取舍,樓豬都要感謝您的閱讀了。期待指點(diǎn)。
者:Jeff Wong
相關(guān)文章
JavaScript限制在客戶區(qū)可見范圍的拖拽(解決scrollLeft和scrollTop的問題)(2)
這篇文章主要介紹了JavaScript限制在客戶區(qū)可見范圍的拖拽,解決scrollLeft和scrollTop的問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05JavaScript切換搜索引擎的導(dǎo)航網(wǎng)頁搜索框?qū)嵗a
這篇文章主要介紹了javascript切換搜索引擎的導(dǎo)航網(wǎng)頁搜索框的實例代碼,非常不錯,具有參考借鑒價值 ,需要的朋友可以參考下2017-06-06javascript中的 object 和 function小結(jié)
JavaScript的面向?qū)ο笫腔谠蔚?,所有對象都有一條屬于自己的原型鏈。Object與Function可能很多看Object instanceof Function , Function instanceof Object都為true而迷惑,所以首先看下對象的實例。2016-08-08檢測一個函數(shù)是否是JavaScript原生函數(shù)的小技巧
這篇文章主要介紹了檢測一個函數(shù)是否是JavaScript原生函數(shù)的小技巧,本文給出了兩種檢測方法,需要的朋友可以參考下2015-03-03JS表示Stack類練習(xí)用棧實現(xiàn)任意進(jìn)制轉(zhuǎn)換
這篇文章主要為大家介紹了JS表示Stack類練習(xí)用棧實現(xiàn)任意進(jìn)制轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Javascript前端事件循環(huán)機(jī)制詳細(xì)講解
單線程的同步等待極大影響效率,任務(wù)不得不一個一個等待執(zhí)行,對于網(wǎng)頁應(yīng)用是無法接受的。所以Javascript使用事件循環(huán)機(jī)制來解決異步任務(wù)的問題。本文就來講講Javascript的事件循環(huán)機(jī)制,希望對你有所幫助2022-12-12微信小程序?qū)崿F(xiàn)的3d輪播圖效果示例【基于swiper組件】
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)的3d輪播圖效果,結(jié)合實例形式分析了微信小程序基于swiper組件相關(guān)屬性設(shè)置、事件響應(yīng)操作技巧,需要的朋友可以參考下2018-12-12