在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 相关文章推荐
js加解密 脚本解密
Feb 22 Javascript
ajax中get和post的说明及使用与区别
Dec 23 Javascript
JS实现方向键切换输入框焦点的方法
Aug 19 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
Dec 07 Javascript
浅谈DOCTYPE对$(window).height()取值的影响
Jul 21 Javascript
js给table赋值的实例代码
Oct 13 Javascript
jquery日历插件e-calendar升级版
Nov 10 Javascript
jQuery插件artDialog.js使用与关闭方法示例
Oct 09 jQuery
jQuery实现监听下拉框选中内容发生改变操作示例
Jul 13 jQuery
微信小程序多音频播放进度条问题
Aug 28 Javascript
node使用Mongoose类库实现简单的增删改查
Nov 08 Javascript
javascript实现前端分页效果
Jun 24 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
win2003服务器使用WPS的COM组件的一些问题解决方法
2012/01/11 PHP
PHP的拦截器实例分析
2014/11/03 PHP
php给每个段落添加空格的方法
2015/03/20 PHP
Symfony2学习笔记之模板用法详解
2016/03/17 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
限制文本字节数js代码
2007/03/06 Javascript
用javascript删除当前行,添加行(示例代码)
2013/11/25 Javascript
JQuery each()嵌套使用小结
2014/04/18 Javascript
全面解析Bootstrap手风琴效果
2020/04/17 Javascript
jquery实现全屏滚动
2015/12/28 Javascript
JavaScript绑定事件监听函数的通用方法
2016/05/14 Javascript
jQuery实现简洁的轮播图效果实例
2016/09/07 Javascript
AngularJs 利用百度地图API 定位当前位置 获取地址信息
2017/01/18 Javascript
javascript 中设置window.location.href跳转无效问题解决办法
2017/02/09 Javascript
浅析Vue实例以及生命周期
2018/08/14 Javascript
nodejs高大上的部署方式(PM2)
2018/09/11 NodeJs
Vue常用的几个指令附完整案例
2018/11/06 Javascript
vue基于better-scroll仿京东分类列表
2020/06/30 Javascript
[54:19]完美世界DOTA2联赛PWL S2 Magma vs PXG 第二场 11.28
2020/12/01 DOTA
python list 合并连接字符串的方法
2013/03/09 Python
基于Python的身份证号码自动生成程序
2014/08/15 Python
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
2015/03/19 Python
python中sleep函数用法实例分析
2015/04/29 Python
Django 路由系统URLconf的使用
2018/10/11 Python
python 接口实现 供第三方调用的例子
2019/08/13 Python
Python Gluon参数和模块命名操作教程
2019/12/18 Python
pycharm 的Structure界面设置操作
2021/02/05 Python
CSS3实现时间轴效果
2016/07/11 HTML / CSS
HTML5新增属性data-*和js/jquery之间的交互及注意事项
2017/08/08 HTML / CSS
高级人员简历的自我评价分享
2013/11/03 职场文书
书香家庭事迹材料
2014/05/09 职场文书
2014年导购员工作总结
2014/11/18 职场文书
诚信考试承诺书范文
2015/04/29 职场文书
2016国庆节67周年红领巾广播稿
2015/12/18 职场文书
Python绘制分类图的方法
2021/04/20 Python
quickjs 封装 JavaScript 沙箱详情
2021/11/02 Javascript