在javascript将NodeList作为Array数组处理的方法


Posted in Javascript onJuly 09, 2010

比如:

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?

1、NodeList为什么不是数组?

验证NodeList是不是数组,最直接的方法也许是试一下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方法。还有疑问吗?这样就结束了吗?这种片面的测试反倒使楼猪无法高枕无忧心安理得了。我们完全可以像证明arguments不是数组一样,也用同样的方法证明NodeList不是数组。看下面的代码吧:
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呢?

2、像操作Array一样操作NodeList

既然NodeList有length,可以for循环索引取值,转换成数组还不是轻而易举?哈哈,最直接的思路是这样的: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就是我们要的数组 
}

明扼要说明一下吧:先new一个Array,遍历NodeList,然后将每一个单独的元素push到数组变量里,最后操作数组变量,over。有没有智商受辱的感觉?
上面不是跟您开玩笑,因为下面是楼猪在网上google到的,两行代码就可以将NodeList转换成Array来使用了:
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附加一个新链接 
}

那么你可能会问,不转换不行吗?没有那么死板,当然是可以的,只要对我们平时熟悉的编码习惯稍微动点小手术就可以了:
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附加一个新链接 
}

到这里,不管有无疑问,实际编程如何取舍,楼猪都要感谢您的阅读了。期待指点。
者:Jeff Wong
Javascript 相关文章推荐
在jQuery 1.5中使用deferred对象的代码(翻译)
Mar 10 Javascript
解决jquery submit()提交表单提示:f[s] is not a function
Jan 23 Javascript
javascript操作数组详解
Dec 17 Javascript
js行号显示的文本框实现效果(兼容多种浏览器 )
Oct 23 Javascript
JS实现的自定义显示加载等待图片插件(loading.gif)
Jun 17 Javascript
使用JQuery选择HTML遍历函数的方法
Sep 17 Javascript
基于JavaScript实现跳转提示页面
Sep 24 Javascript
js实现移动端导航点击自动滑动效果
Jul 18 Javascript
JSON 数据格式详解
Sep 13 Javascript
vue与TypeScript集成配置最简教程(推荐)
Oct 17 Javascript
Vue中 v-if 和v-else-if页面加载出现闪现的问题及解决方法
Oct 12 Javascript
Echarts实现多条折线可拖拽效果
Dec 19 Javascript
jquery multiSelect 多选下拉框
Jul 09 #Javascript
IE8 chrome中table隔行换色解决办法
Jul 09 #Javascript
jQuery EasyUI NumberBox(数字框)的用法
Jul 08 #Javascript
JSON.parse 解析字符串出错的解决方法
Jul 08 #Javascript
location.href 在IE6中不跳转的解决方法与推荐使用代码
Jul 08 #Javascript
JQuery从头学起第三讲
Jul 06 #Javascript
一步一步制作jquery插件Tabs实现过程
Jul 06 #Javascript
You might like
第二节 对象模型 [2]
2006/10/09 PHP
php 中的closure用法详解
2017/06/12 PHP
PHP之认识(二)关于Traits的用法详解
2019/04/11 PHP
用Javscript实现表单复选框的全选功能
2007/05/25 Javascript
用 Javascript 验证表单(form)中多选框(checkbox)值
2009/09/08 Javascript
基于jquery的用鼠标画出可移动的div
2012/09/06 Javascript
Javascript中的异步编程规范Promises/A详细介绍
2014/06/06 Javascript
浅谈javascript中字符串String与数组Array
2014/12/31 Javascript
再谈JavaScript线程
2015/07/10 Javascript
使用BootStrap和Metroui设计的metro风格微网站或手机app界面
2016/10/21 Javascript
使用 bootstrap modal遇到的问题小结
2016/11/09 Javascript
Java与JavaScript中判断两字符串是否相等的区别
2017/03/13 Javascript
elementui的默认样式修改方法
2018/02/23 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
[03:07]DOTA2英雄基础教程 冰霜诅咒极寒幽魂
2013/12/06 DOTA
python选择排序算法的实现代码
2013/11/21 Python
python中list列表的高级函数
2016/05/17 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
使用Python批量修改文件名的代码实例
2019/01/24 Python
Python利用requests模块下载图片实例代码
2019/08/12 Python
pytorch的batch normalize使用详解
2020/01/15 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
2020/02/04 Python
python实现FTP文件传输的方法(服务器端和客户端)
2020/03/20 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
HTML5 新表单类型示例代码
2018/03/20 HTML / CSS
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
阿联酋电子产品购物网站:Menakart
2017/09/15 全球购物
亚洲航空公司官方网站:AirAsia
2019/11/25 全球购物
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
2013/04/11 面试题
毕业生求职推荐信
2013/11/04 职场文书
综合实践教学反思
2014/01/31 职场文书
低碳日宣传活动总结
2014/07/09 职场文书
电子银行业务授权委托书
2014/10/10 职场文书
党委书记个人检查对照材料思想汇报
2014/10/11 职场文书
有限责任公司股东合作协议书
2014/12/02 职场文书
化验员岗位职责
2015/02/14 职场文书