NodeList
是一个类似于数组,但又有区别于数组的一种类数组对象,为什么说NodeList
类似于数组呢,因为NodeList
对象,可以使用和数组取值方式同样的取值方式(中括号加下标取值),但是却又没有Array
对象中常用的方法,slice
,push
,pop
等,又不同于数组,是因为NodeList
是一个实时变化的数组(大多数情况下,它是一个live
的集合),即如果文档中的节点树发生变化,则已经存在的NodeList
对象也可能会变化。
可以参考以下资料:NodeList 和 NodeList 对象。
概述
NodeList
对象是一个节点的集合,通常是由getElementsByTagName
, getElementsByTagNameNS
, Node.childNodes
, querySelectorAll
, getElementsByClassName
等方法返回的.
虽然说,NodeList
大多数情况下,是一个live
的集合,但并不是所有的NodeList
对象,都是live
的集合,比如这里querySelectorAll
获取的NodeList
集合,它就不是一个实时更新的集合。
你也可以点击查看:demo。
我们也都知道,在所有的操作中,DOM
操作是性能最差的,所以如果可以,就尽量的少使用DOM
操作,这里的NodeList
对象,如果是一个live
的集合,那么在DOM
结构进行变化时,很明显的会进行相关的DOM
操作(引擎自己实现的),从而重新定义它的length
的值,所以这样的代码并不是一个优雅的代码,可是querySelectorAll
呢,这个方法在低版本的浏览器中是不支持的,所以,有时候,我们会把NodeList
对象,转换成Array对象进行统一的处理。
问题
在jQuery
中,对于NodeList
对象转换成Array
对象,是这样处理的:
var links = document.getElementsByTagName('a');
var ArrayObj = [].slice.call(links);
经过这样的转换,把links
变成一个数组,我们可以这样证明:
console.log(Object.getOwnPropertyNames(links.__proto__));
var ArrayObj = [].slice.call(links);
console.log(Object.getOwnPropertyNames(ArrayObj.__proto__));
console.log(ArrayObj.__proto__ === Array.prototype); //true
看起来很不错的样子,可是问题出现了,当我们在IE8-
的浏览器这样使用时,却出了问题,在NodeList
转换成Array
对象时,浏览器直接抛出一个错误:
这是为什么?因为在IE8-
的浏览器中,HTML
的DOM
对象,不是继承自Object
对象的?这里关于为什么DOM
对象不继承自Object
对象,就会导致无法使用Array
对象中的方法,根本原因,不能明了。
而从抛出的错误的原因可以看出,是在Array.prototype.slice
函数执行时,内部的this
对象调用了一个属于Object
对象的方法或者属性,而这个方法或者属性是IE8-
的DOM
对象中不存在的一个。具体是哪个属性或者方法才会出现这个问题,未知~~
当然,这里出了这个问题,就会有相应的解决方法,方法也算是很简单,只要重写一下就行了,例如下面的样子,最简单的写法:
Array.prototype.slice = function(){
var ele = this,
i = 0,
len = ele.length,
res = [];
for(;i<len;i++){
res.push(ele[i]);
}
return res;
}
var links = document.getElementsByTagName('a');
console.log([].slice.call(links));
感觉这里有点扯,能力有限,暂时只能理解到这里,更深层次的原因,继续寻找,也欢迎赐教!
补充
2014-6-21补充:NodeList这种类型,之所以被称之为live数组,也是因为它们的另外的名字,类数组,想想类数组是什么,想想数组时属于什么样的类型,数组是Array类型,是一个引用类型,类数组是一个Object类型,Object也是属于引用类型。引用类型有一个特点就是,如果不重新赋值,那么对于引用类型的更改,都是在更改同一个引用类型的。
例如:
var a = [];
a[0] = 1;
console.log(a[0]); //1
我认为,live
类的实时更新到元素中去,它的根本原因,就在于,它们获取到的值,是一个类数组,是一个引用类型的数据类型。
暂时这么理解,如果有任何错误,请指教,谢谢!