假设我有以下列表:
<ol>
<li>Cookies <ol>
<li>Coffee</li>
<li>Milk</li>
<li class="test1">Chocolate </li>
</ol>
我在html结尾处执行此选择
var nodes = document.querySelectorAll('li:first-of-type');
当我在Chrome nodes.forEach
中尝试时,它给了我一个错误。当我看到它看起来像一个数组的值。我实际上能够使用常规来导航它,如:
for(var i=0;i<nodes.length;i++){
nodes[i].onclick= function(){ alert('Hello!'); };
}
那么,document.querySelectorAll
的实际返回类型是什么?为什么数组方法不起作用?
所以,它看起来像一个数组,可以解决它使它像数组一样工作,但它不是一个数组?
答案 0 :(得分:9)
结果的类型是NodeList。
由于它是一个类似于Array的对象,你可以像这样运行map
,forEach
和其他Array.prototype函数:
var result = document.querySelectorAll('a');
Array.prototype.map.call(result, function(t){ return t; })
Array原型中的map
,forEach
,any
和其他函数适用于类似Array的对象。例如,让我们定义一个具有数字索引(0,1)和长度属性的对象文字:
var arrayLike = { '0': 'a', '1': 'b', length: 2};
应用于arrayLike
对象的forEach方法将类似于真实数组。
Array.prototype.forEach.call(arrayLike, function(x){ console.log(x) } ); //prints a and b
答案 1 :(得分:5)
在documentation中,它说:
[返回的元素列表]是元素对象的非实时
NodeList
。
NodeList
与数组(完全不同的原型链)不同,文档还告诉您为什么不能使用forEach
:
为什么我无法在
forEach
上使用map
或NodeList
?
NodeList
与数组非常相似,并且很容易对它们使用Array.prototype
方法,但它们没有这些方法。JavaScript有一个基于原型的继承机制,用于内置对象(如
Array
s)和宿主对象(如NodeList
s)。Array
个实例继承了数组方法(例如forEach
或map
),因为它们的原型链如下所示:
myArray --> Array.prototype --> Object.prototype --> null
(对象的原型链可以通过多次调用Object.getPrototypeOf来获得。)
forEach
,map
等都是Array.prototype
对象的自有属性。与数组不同,
NodeList
原型链如下所示:
myNodeList --> NodeList.prototype --> Object.prototype --> null
NodeList.prototype
包含item方法,但不包含Array.prototype
方法,因此无法在NodeLists
上使用。
但是,有一些解决方法。再次从文档中,您可以直接使用Array.prototype.forEach
和Array.prototype.map
方法:
var forEach = Array.prototype.forEach;
var divs = document.getElementsByTagName( 'div' );
var firstDiv = divs[ 0 ];
forEach.call(firstDiv.childNodes, function( divChild ){
divChild.parentNode.style.color = '#0F0';
});