原文引用脚本之家作者:Jeff Wong,谢谢大神提供资源

在Web前端编程中,我们通常会通过document.getElementsByTagName或者document.getElementsByClassName的方法取出一组相同标签的dom元素。如下

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循环索引取值,转换成数组还不是轻而易举?哈哈,最直接的思路是这样的:

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附加一个新链接
}

到这里,不管有无疑问,实际编程如何取舍,楼猪都要感谢您的阅读了。期待指点。 

JavaScript NodeList和Array的更多相关文章

  1. 在javascript中NodeList和Array的区别及转换方法

    随着深入理解javascript 后对于一些小知识的了解慢慢加深,这里说的是关于nodelist和array的区别,相信你一定用过toarray()方法,但是这里通过js 的方法讲解nodelist ...

  2. ExtJS学习-----------Ext.Array,ExtJS对javascript中的Array的扩展

    关于ExtJS对javascript中的Array的扩展.能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 因为 ...

  3. javascript类型系统之Array

    原文:javascript类型系统之Array 目录 [1]数组创建 [2]数组操作 [3]继承的方法 [4]实例方法 数组转换 数组检测 栈和队列 排序方法 操作方法 位置方法 前面的话 数组是一组 ...

  4. 从头开始学JavaScript (十二)——Array类型

    原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = ne ...

  5. JavaScript中数组Array方法详解

    ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...

  6. JavaScript高级编程——Array数组迭代(every()、filter()、foreach()、map()、some(),归并(reduce() 和reduceRight() ))

    JavaScript高级编程——Array数组迭代(every().filter().foreach().map().some(),归并(reduce() 和reduceRight() )) < ...

  7. Javascript中的Array(数组) 、{}(映射) 与JSON解析

    做网页总会使用javascript,使用javascript总会使用JSON.最近用到一下,就写写. 下面是总结: 1.将javascript中的Array和{}转化为json字符串可以使用json2 ...

  8. JavaScript中的Array.prototype.slice.call()方法学习

    JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外 ...

  9. 详解Javascript中的Array对象

    基础介绍 创建数组 和Object对象一样,创建Array也有2种方式:构造函数.字面量法. 构造函数创建 使用构造函数的方式可以通过new关键字来声明,如下所示: 12 var arr = new ...

随机推荐

  1. ECSHOP如何解决购物车中商品自动消失问题

    最近有客户反映关于ECShop购物车的问题:需要加入多个商品到购物车时,发现之前加入到购物车的商品都自动消失了,只有最后一次加入购物车的商品在里面.那么,这是什么原因呢? 因为ECShop的SESSI ...

  2. Demo学习: Closable Tabs

    Closable Tabs 给tab页添加关闭按钮,设置UniTabSheet.Closable = True这样在tab页的右上角就会出现关闭图标,点击可以关闭当前tab页面: 1. 直接关闭,完成 ...

  3. Spark Streaming揭秘 Day29 深入理解Spark2.x中的Structured Streaming

    Spark Streaming揭秘 Day29 深入理解Spark2.x中的Structured Streaming 在Spark2.x中,Spark Streaming获得了比较全面的升级,称为St ...

  4. ubuntu中替代visio的软件 dia

    ubuntu 中 软件  dia 可以替代 ms-visio软件. 安装过程可以在线安装: sudo apt-get install dia

  5. 使用bootstrap+asp.net mvc4+IBatis.Net实现的小程序

    这个项目用到了三个技术点 1.bootstap 3.0 2.asp.net mvc4 3.IBatis.Net 这个三个技术点分别解决前端界面展示.中间mvc路由控制.实体框架映射数据访问 重点分页问 ...

  6. C语言获取网页源代码的学习所得

    研究了一天这个玩意感觉挺有意思的. 刚开始是什么都不懂,现在写出来一段代码感觉略微有点意思了. 下面我分享一下学习过程和自己的理解. 整体过程大概就是如下情况: 先搜了一下别人的写这个东西的代码. 研 ...

  7. RegisterClientScriptBlock CommandName 模块列 操作完成 提示

    this.ClientScript.RegisterClientScriptBlock(this.GetType(), "Remind", "alert('获取成功!') ...

  8. 选择排序O(n^2)与快速排序O(nlogn)的优越性代码体现

    随机函数生成一个超大数组: [code]: #include <iostream> #include <stdio.h> #include<time.h> #inc ...

  9. 相似元素存在的意义---HTML&CSS

    1.<q> 效果: 告诉浏览器这是一段短引用,让浏览器以合适的方法来显示 注: 不能直接以双引号直接代替<q>,因为有些浏览器<q>的效果不是双引号. 不要忘了移动 ...

  10. 【扩展欧几里得】Bzoj 1407: [Noi2002]Savage

    Description Input 第1行为一个整数N(1<=N<=15),即野人的数目.第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0 ...