JavaScript NodeList和Array
原文引用脚本之家作者: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的更多相关文章
- 在javascript中NodeList和Array的区别及转换方法
随着深入理解javascript 后对于一些小知识的了解慢慢加深,这里说的是关于nodelist和array的区别,相信你一定用过toarray()方法,但是这里通过js 的方法讲解nodelist ...
- ExtJS学习-----------Ext.Array,ExtJS对javascript中的Array的扩展
关于ExtJS对javascript中的Array的扩展.能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 因为 ...
- javascript类型系统之Array
原文:javascript类型系统之Array 目录 [1]数组创建 [2]数组操作 [3]继承的方法 [4]实例方法 数组转换 数组检测 栈和队列 排序方法 操作方法 位置方法 前面的话 数组是一组 ...
- 从头开始学JavaScript (十二)——Array类型
原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = ne ...
- JavaScript中数组Array方法详解
ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...
- JavaScript高级编程——Array数组迭代(every()、filter()、foreach()、map()、some(),归并(reduce() 和reduceRight() ))
JavaScript高级编程——Array数组迭代(every().filter().foreach().map().some(),归并(reduce() 和reduceRight() )) < ...
- Javascript中的Array(数组) 、{}(映射) 与JSON解析
做网页总会使用javascript,使用javascript总会使用JSON.最近用到一下,就写写. 下面是总结: 1.将javascript中的Array和{}转化为json字符串可以使用json2 ...
- JavaScript中的Array.prototype.slice.call()方法学习
JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外 ...
- 详解Javascript中的Array对象
基础介绍 创建数组 和Object对象一样,创建Array也有2种方式:构造函数.字面量法. 构造函数创建 使用构造函数的方式可以通过new关键字来声明,如下所示: 12 var arr = new ...
随机推荐
- 百度地图API实现多区域标记
最近遇到一个业务就是需要需要在地图上标记多个区域.一般餐饮业做外卖的,配送范围一般是多区域的,那么在地图上标记配送范围的时候就需要能标记多个区域.长话短说,最初的实现原型的截图如下:
- mySQL时间
" and day='".date('Y-m-d',strtotime($day_g)). "'"; 时间如: 2014-09-09 and day>= ...
- WRS是什么?
全球参考系(WRS)是为卫星下行数据服务而建立的一种全球符号坐标系统,本文详细介绍了Landsat卫星的轨道特性,给出了相应的WRS网格坐标位置的估算方法,并给出了估算的结果。对该方法的研究为地面应用 ...
- WebApi中帮助页Description的中文显示
转自:http://edi.wang/post/2013/10/28/auto-generate-help-document-aspnet-webapi 我选择Web API的一个重要原因就是因为可以 ...
- Lua基础之语法
目录:1.输出2.注释3.控制语句4.赋值语句5.运算符6.关键字7.变量类型8.其他 原文地址http://blog.csdn.net/dingkun520wy/article/details/49 ...
- [SQL SERVER系列]之常用函数和开窗函数介绍及实例
本文主要介绍SQL SERVER数据库中一些常用的系统函数及其SQL SERVER 2005以上支持的开窗函数. 1.常用函数 --从字符串右边截取指定字符数 select RIGHT('HELLO' ...
- 1053: [HAOI2007]反素数ant - BZOJ
Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数 ...
- 1050 棋盘染色 2 - Wikioi
题目描述 Description 有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块. 输入描述 Input Description 第一行一个 ...
- Linux命令ln的使用
ln是linux中一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个链接,这个命令最常用的参数是-s,具体用法是:ln –s 源文件 目标文件. 当我们需要在不同的目录,用到相同的文件时, ...
- 如何通过 OAuth 2.0 使 iOS Apps 集成 LinkedIn 登录功能?
社交网络早已成为人们日常生活的一部分.其实,社交网络也是编程生活的一部分,大多数 App 必须通过某种方式与社交网络交互,传送或接收与用户相关的数据.大多数情况下,用户需要登录某种社交网络,授权 Ap ...