假设我有以下列表:
<ol>
<li>Cookies <ol>
<li>Coffee</li>
<li>Milk</li>
<li class="test1">Chocolate </li>
</ol>
Run Code Online (Sandbox Code Playgroud)
我在我的HTML结尾处执行此选择
var nodes = document.querySelectorAll('li:first-of-type');
Run Code Online (Sandbox Code Playgroud)
当我在Chrome中尝试时,nodes.forEach它给了我一个错误.当我看到它看起来像一个数组的值.我实际上能够使用常规导航它像:
for(var i=0;i<nodes.length;i++){
nodes[i].onclick= function(){ alert('Hello!'); };
}
Run Code Online (Sandbox Code Playgroud)
那么,实际返回的类型是document.querySelectorAll什么?为什么数组方法不起作用?
所以,它看起来像一个数组,可以解决它使它像数组一样工作,但它不是一个数组?
结果的类型是NodeList.因为它是一个类似数组的对象,就可以运行map,forEach而其他Array.prototype这样它的功能:
var result = document.querySelectorAll('a');
Array.prototype.map.call(result, function(t){ return t; })
Run Code Online (Sandbox Code Playgroud)
的map,forEach,any在阵列状物体的数组原型工作等功能.例如,让我们用数字索引(0,1)和长度属性定义一个对象文字:
var arrayLike = { '0': 'a', '1': 'b', length: 2};
Run Code Online (Sandbox Code Playgroud)
应用于arrayLike对象的forEach方法将类似于真实数组.
Array.prototype.forEach.call(arrayLike, function(x){ console.log(x) } ); //prints a and b
Run Code Online (Sandbox Code Playgroud)
在文档中,它说:
[返回的元素列表]是
NodeList元素对象的非实时元素.
NodeList与数组(完全不同的原型链)不同,文档也告诉您为什么不能使用forEach:
为什么我不能使用
forEach或map上NodeList?
NodeList非常像数组使用Array.prototype,它们很容易使用它们,但是它们没有那些方法.JavaScript有一个基于原型的继承机制,用于内置对象(如
Arrays)和宿主对象(如NodeLists).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';
});
Run Code Online (Sandbox Code Playgroud)