Array.prototype。*在类似对象或永远本机/主机对象的数组上的可移植性

时间:2014-09-04 23:17:59

标签: javascript standards portability ecmascript-5

许多Array.prototype函数的ESMA 262 5.1表示它们故意通用,并根据[[Get]][[Put]]等操作进行了描述{{1 },但也需要Object属性。

因此他们可以使用内置对象,例如:

length

对于原生对象标准,请注意:

  

是否可以成功应用推送功能       到宿主对象是依赖于实现的。

obj = {"a":true, "length":10}; Array.prototype.push.call(obj, -1); console.log(obj); // Object { 10: -1, a: true, length: 11 } 主持人对象吗?似乎所有DOM(如arguments)都是宿主对象。它们适用于现代浏览器。

MDN docs警告NodeList。其他浏览器怎么样?那么< IE9本机对象怎么样? Rhino / Nashorn原生对象怎么样?

更新 @ jfriend00嗯,我没有考虑nodejs操作......在ECMA 5.1中,我发现了有关此类情况的特别说明:

[[Put]]

所以在不好的情况下你会得到Host objects may implement these internal methods in any manner unless specified otherwise; for example, one possibility is that [[Get]] and [[Put]] for a particular host object indeed fetch and store property values but [[HasProperty]] always generates false. However, if any specified manipulation of a host object's internal properties is not supported by an implementation, that manipulation must throw a TypeError exception when attempted.

2 个答案:

答案 0 :(得分:3)

由于你从来没有真正得到完整的答案,我会抓住你回答你发布的一些问题。

  

参数是宿主对象吗?

arguments是Javascript语言的一部分,而不是宿主对象。它具有非常明确定义的行为,在strict模式下运行时已被修改。由于arguments不会超出当前函数调用(甚至不在闭包中)并且因为它不是可变的,因此处理arguments对象的常用方法是立即将副本复制到一个真正的数组中然后,您可以在其上使用所有常规数组方法,它可以在一个闭包中保留,以便由本地函数访问。

  

MDN docs警告&lt; IE9。那么其他浏览器呢?

这里对特定浏览器的概括并不是非常具体。相反,您必须检查特定对象,然后检查浏览器的特定版本。较早版本的IE确实因为拥有与Javsacript(以这种方式)无法互操作的主机对象而闻名,但你真的必须检查一个特定的对象才能知道你能做什么和不能做什么。 / p>

  

nodejs原生对象怎么样?

node.js比浏览器更纯粹的Javascript环境,因为没有DOM,没有window对象等等...你有没有任何特定的node.js对象,你想问一下?在我对node.js的一些有限经验中,我只是看到了实际的JS对象,尽管node.js有许多与OS接口的地方,所以这些接口中可能还有一些非JS对象(我没有遇到过但是,这是一种可能性。)

  

所以在坏的情况下你得到TypeError!

正如我在评论中所说,使用任何试图修改数组的数组对象(例如.splice())很可能会导致主机对象出现问题,因为许多主机对象不能直接修改。另外阅读规范并假设旧浏览器都遵循规范(没有进行大量测试来验证)可能是危险的。特别是,IE的旧版本因不遵守规范而闻名。所以,再说一遍,你不能只假设没有适当的测试就会得到TypeError


如果您正在寻找通用的安全编码方法,那么将类似数组的主机对象复制到实际数组中然后在实际数组上使用数组操作永远不会出错。这保证是安全的。有Array.prototype.slice的跨浏览器polyfill适用于所有浏览器,可以复制到MDN page for .slice()上的实际数组中。如果您只支持IE 9及更高版本,则不需要填充。

并且,永远不要假设任何更改类数组对象的操作在主机对象上通常是安全的(可能存在特定的异常,但您必须进行大量测试才能确定)。我的偏好是编写我知道安全的代码,并且不需要进行大量测试来保证这一点。复制到一个实际的数组每次都会给我这个。

答案 1 :(得分:1)

如果你想确定它能够正常工作,最好先将它转换为数组。

要将类似数组的对象转换为数组,可以使用ES6 Array.from。目前只有Firefox 32支持它,但有一个polyfill

或者,[].slice.call(arrayLike)适用于大多数浏览器。