在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 相关文章推荐
firefox中JS读取XML文件
Dec 21 Javascript
Javascript 类、命名空间、代码组织代码
Jul 31 Javascript
UpdatePanel和Jquery冲突的解决方法
Apr 01 Javascript
浅谈Node.js中的定时器
Jun 18 Javascript
基于javascript代码检测访问网页的浏览器呈现引擎、平台、Windows操作系统、移动设备和游戏系统
Dec 03 Javascript
基于JavaScript实现定时跳转到指定页面
Jan 01 Javascript
jQuery对checkbox 复选框的全选全不选反选的操作
Aug 09 Javascript
Jquery把获取到的input值转换成json
May 15 jQuery
ES6 javascript中class类的get与set用法实例分析
Oct 30 Javascript
Vue中this.$router.push参数获取方法
Feb 27 Javascript
JS/jQuery实现超简单的Table表格添加,删除行功能示例
Jul 31 jQuery
JavaScript实现文件下载并重命名代码实例
Dec 12 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
手冲咖啡应该是现代精品咖啡店的必备选项吗?
2021/03/03 冲泡冲煮
PHP计算近1年的所有月份
2017/03/13 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
基于jQuery实现点击同时更改两个iframe的网址
2010/07/01 Javascript
jQuery的实现原理的模拟代码 -4 重要的扩展函数 extend
2010/08/03 Javascript
javascript中typeof操作符和constucor属性检测
2015/02/26 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
总结JavaScript三种数据存储方式之间的区别
2016/05/03 Javascript
Javascript字符串拼接小技巧(推荐)
2016/06/02 Javascript
Node.js搭建小程序后台服务
2018/01/03 Javascript
AngularJS使用$http配置对象方式与服务端交互方法
2018/08/13 Javascript
详解vue中使用微信jssdk
2019/04/19 Javascript
微信小程序+腾讯地图开发实现路径规划绘制
2019/05/22 Javascript
node.js中npm包管理工具用法分析
2020/02/14 Javascript
浅谈vue中使用编辑器vue-quill-editor踩过的坑
2020/08/03 Javascript
TypeScript 运行时类型检查补充工具
2020/09/28 Javascript
[05:39]2014DOTA2西雅图国际邀请赛 淘汰赛7月14日TOPPLAY
2014/07/14 DOTA
[03:59]第二届DOTA2亚洲邀请赛选手传记-VGJ.rOtk
2017/04/03 DOTA
[00:34]拔城逐梦,热血永恒!2020(秋)完美世界城市挑战赛报名开启
2020/10/09 DOTA
[02:36]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma 选手采访
2021/03/11 DOTA
跟老齐学Python之有容乃大的list(1)
2014/09/14 Python
pyecharts绘制中国2020肺炎疫情地图的实例代码
2020/02/12 Python
python游戏开发的五个案例分享
2020/03/09 Python
金宝贝童装官网:Gymboree
2016/08/31 全球购物
奥地利汽车配件店:Pkwteile.at
2017/03/10 全球购物
俄罗斯Sportmarket体育在线商店:用于旅游和户外活动
2019/11/12 全球购物
体育老师的教学自我评价分享
2013/11/19 职场文书
总务岗位职责
2013/11/19 职场文书
创业大赛策划书
2014/03/01 职场文书
对教师的评语
2014/04/28 职场文书
社会实践活动总结范文
2014/07/03 职场文书
家具公司总经理岗位职责
2014/07/08 职场文书
小学五一劳动节活动总结
2015/02/09 职场文书
辩论赛主持人开场白
2015/05/29 职场文书
运动会主持词大全
2015/07/02 职场文书
52条SQL语句教你性能优化
2021/05/25 MySQL