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

时间:2021-05-27 01:22:08

It is my understanding that IE8 has access to the Array.prototype.slice method. Yet when I try to call it to turn a NodeList into an array, it gives me the error Array.prototype.slice: 'this' is not a JavaScript object. You can check it out here, or look at my code here:

据我所知,IE8可以访问Array.prototype.slice方法。然而,当我尝试调用它将NodeList转换为数组时,它给出了错误Array.prototype.slice:'this'不是JavaScript对象。你可以在这里查看,或者在这里查看我的代码:

HTML

HTML

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

JavaScript

JavaScript的

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

What's going on here?

这里发生了什么?

4 个解决方案

#1


8  

Update: A NodeList can be treated as an array in some ways - you don't actually have to do anything special with it before you can loop over it, for example:

更新:NodeList可以在某些方面被视为一个数组 - 在你可以循环之前,你实际上不必对它做任何特殊的事情,例如:

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

This will create an array with all of the nodes that matched when you ran document.getElementsByTagName()

这将创建一个数组,其中包含运行document.getElementsByTagName()时匹配的所有节点。

See this question for a full explanation of why slice works with a NodeList in some browsers but not others, but it boils down this this sentence from the specification:

请参阅此问题,以获得有关为什么切片在某些浏览器中与NodeList一起工作而不是其他浏览器的完整解释,但它从规范中将这句话归结为:

Whether the slice function can be applied successfully to a host object is implementation-dependent.

切片功能是否可以成功应用于主机对象取决于实现。

#2


2  

The error message is accurate - your nodelist is not a JavaScript object, it is a "Host Object", which you can't necessarily pass around like regular JavaScript objects. Run this code in IE8's JavaScript console:

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

document.querySelectorAll("div") instanceof Object

It returns false.

它返回false。

#3


0  

I assume that you want to keep the same content even if the NodeList set changes.

我假设您希望保持相同的内容,即使NodeList集更改。

If it's that case, bad news : IE8 is broken. And it can't handle using slice on NodeList.

如果就是这样,坏消息:IE8坏了。并且它无法处理在NodeList上使用切片。

So you will need to use a fallback and make the "slice" yourself when slice fails (by using a try/catch).

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

Note that If you don't expect the DOM to change, and if an array-like object is enough, then you can just use the NodeList like any other array (except that it is not, and that perhaps it will be modified if the DOM changes).

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

[edit] Actually it's not a broken design, it's allowed by the standard (as stated by the link in Kelvin Mackay's comment)

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

#4


0  

Using Array.prototype.slice to convert a NodeList to array won't work because of these two reasons:

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

  • slice method returns the existing array element(s).

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

  • Array.prototype is not an instance of Array object. It's merely an object container of properties that will be inherited by all Array object instances. So it doesn't have the actual array value.

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

Converting a NodeList or HTMLCollection to an array is usually done using for... loop. But it can also be done using dynamically created disposable array:

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

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

It can also be done using bound call to a method from Array.prototype, although this is uncommon and isn't a recommended way. Below example is basically same as above.

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

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

#1


8  

Update: A NodeList can be treated as an array in some ways - you don't actually have to do anything special with it before you can loop over it, for example:

更新:NodeList可以在某些方面被视为一个数组 - 在你可以循环之前,你实际上不必对它做任何特殊的事情,例如:

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

This will create an array with all of the nodes that matched when you ran document.getElementsByTagName()

这将创建一个数组,其中包含运行document.getElementsByTagName()时匹配的所有节点。

See this question for a full explanation of why slice works with a NodeList in some browsers but not others, but it boils down this this sentence from the specification:

请参阅此问题,以获得有关为什么切片在某些浏览器中与NodeList一起工作而不是其他浏览器的完整解释,但它从规范中将这句话归结为:

Whether the slice function can be applied successfully to a host object is implementation-dependent.

切片功能是否可以成功应用于主机对象取决于实现。

#2


2  

The error message is accurate - your nodelist is not a JavaScript object, it is a "Host Object", which you can't necessarily pass around like regular JavaScript objects. Run this code in IE8's JavaScript console:

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

document.querySelectorAll("div") instanceof Object

It returns false.

它返回false。

#3


0  

I assume that you want to keep the same content even if the NodeList set changes.

我假设您希望保持相同的内容,即使NodeList集更改。

If it's that case, bad news : IE8 is broken. And it can't handle using slice on NodeList.

如果就是这样,坏消息:IE8坏了。并且它无法处理在NodeList上使用切片。

So you will need to use a fallback and make the "slice" yourself when slice fails (by using a try/catch).

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

Note that If you don't expect the DOM to change, and if an array-like object is enough, then you can just use the NodeList like any other array (except that it is not, and that perhaps it will be modified if the DOM changes).

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

[edit] Actually it's not a broken design, it's allowed by the standard (as stated by the link in Kelvin Mackay's comment)

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

#4


0  

Using Array.prototype.slice to convert a NodeList to array won't work because of these two reasons:

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

  • slice method returns the existing array element(s).

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

  • Array.prototype is not an instance of Array object. It's merely an object container of properties that will be inherited by all Array object instances. So it doesn't have the actual array value.

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

Converting a NodeList or HTMLCollection to an array is usually done using for... loop. But it can also be done using dynamically created disposable array:

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

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

It can also be done using bound call to a method from Array.prototype, although this is uncommon and isn't a recommended way. Below example is basically same as above.

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

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