IE8中的“Array.prototype.slice:'this'不是JavaScript对象”错误

时间:2012-11-09 23:56:16

标签: javascript arrays dom prototype nodelist

据我了解,IE8可以访问Array.prototype.slice方法。然而,当我尝试将其调用为NodeList数组时,它会给我错误Array.prototype.slice: 'this' is not a JavaScript objectYou can check it out here,或者查看我的代码:

HTML

<div id="test">Test</div>

的JavaScript

var divs = document.getElementsByTagName('div');
divs = Array.prototype.slice.call(divs);
console.log(divs);

这里发生了什么?

4 个答案:

答案 0 :(得分:8)

更新:在某些方面可以将NodeList视为数组 - 您实际上不必对它进行任何特殊操作,然后才能循环它,例如:

var aDivs = [];
for (var = i = 0; i < divs.length; i++) {
    aDivs.push(divs[i]);
}

这将创建一个数组,其中包含您在运行document.getElementsByTagName()

时匹配的所有节点

有关slice在某些浏览器中使用NodeList而不是其他浏览器的原因的详细说明,请参阅this question,但它从规范中将这句话归结为:

  

切片功能是否可以成功应用于主机对象是依赖于实现的。

答案 1 :(得分:2)

错误消息准确无误 - 您的节点列表不是JavaScript对象,它是“Host Object”,您不一定会像常规JavaScript对象一样传递它。在IE8的JavaScript控制台中运行此代码:

document.querySelectorAll("div") instanceof Object

返回false

答案 2 :(得分:0)

我假设您希望保留相同的内容,即使NodeList集发生了变化。

如果是这种情况,坏消息:IE8坏了。它无法处理在NodeList上使用切片。

因此,您需要使用回退并在切片失败时自己制作“切片”(通过使用try / catch)。

请注意,如果您不希望更改DOM,并且类似于数组的对象就足够了,那么您可以像任何其他数组一样使用NodeList(除非它不是,并且它可能会是如果DOM改变则修改。)

[edit] 实际上它不是一个破碎的设计,它是标准所允许的(正如Kelvin Mackay评论中的链接所述)

答案 3 :(得分:0)

使用Array.prototype.sliceNodeList转换为数组将无法正常工作,原因如下:

  • slice方法返回现有的数组元素。

  • Array.prototype不是Array对象的实例。它只是一个属性的对象容器,将由所有Array对象实例继承。所以它没有实际的数组值。

通常使用NodeList循环将HTMLCollectionfor...转换为数组。但它也可以使用动态创建的一次性数组来完成:

var divs = ([]).concat(document.getElementsByTagName('div'));

也可以使用对来自Array.prototype的方法的绑定调用来完成,尽管这不常见且不是推荐的方法。以下示例与上述基本相同。

var divs = Array.prototype.concat.apply([], document.getElementsByTagName('div'));