Array.prototype的可移植性。*在阵列状物体或曾经本地/主机对象(Portability

2019-10-20 21:38发布

ESMA 262 5.1对很多Array.prototype功能,说他们是故意通用和来描述[[Get]] [[Put]] ,对等操作Object ,还需要length属性。

所以他们允许在工作内置的对象,例如:

obj = {"a":true, "length":10};
Array.prototype.push.call(obj, -1);
console.log(obj); // Object { 10: -1, a: true, length: 11 }

对于原生对象的标准有注意事项:

是否推功能可以成功地应用到一个宿主对象是实现相关的。

arguments主机对象? 似乎所有的DOM(如NodeList )是主机对象。 而它们在现代浏览器。

MDN文档警告< IE9 。 什么其他的浏览器? 怎么样nodejs本地对象? 什么犀牛/犀牛本地对象?

UPDATE @ jfriend00嗯,我也没多想[[Put]]操作......在ECMA 5.1,我发现对这种情况特别提示:

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.

因此,在不好的情况下,你得到TypeError

Answer 1:

因为你从来没有真正得到一个完整的答案,我会采取刺伤在回答一些您发布的问题。

被争论主机对象?

arguments是JavaScript语言,而不是一个宿主对象的一部分。 它在运行时,已经修改了一些相当明确的行为strict模式。 由于arguments超出当前函数调用(即使不是在一个封闭)不会持续,因为它并不意味着是可变的,处理参数通常的方式目的是立即复制到一个真正的数组,然后可在使用其上的所有正常阵列方法,它可以在一个关闭持续到由本地功能进行访问。

MDN文档警告<IE9。 什么其他的浏览器?

这不是很具体的在这里概括特定的浏览器。 相反,你必须检查特定对象和浏览器,然后特定版本。 IE浏览器的老版本也有具有不与Javsacript(以这种方式)进行互操作,以及主机对象的声誉,但你真的要检查特定对象知道你能做和不能做什么。

什么本土的NodeJS对象?

Node.js的是更纯粹的JavaScript环境不是浏览器,因为没有DOM,没有window对象,等等......你心里有任何具体的node.js的对象,你要问什么? 在我与node.js的比较有限的经验,我只是看到实际的JS对象,虽然有很多地方是Node.js的界面与操作系统,所以也许有在这些接口的一些非JS对象(我还没有遇到过任何然而,那不过是一种可能性)。

因此,在不好的情况下,你得到类型错误!

正如我在我的评论说,利用试图修改数组如任何数组对象.splice()是很容易造成尽可能多的主机对象并不意味着要直接修改主机对象的问题。 加上阅读说明书,并假设旧的浏览器都遵循规范(不广泛的测试,以验证)可能是危险的。 特别是,旧版本的IE是著名的不遵守规范。 所以,再一次,你不能只是假设你会得到一个TypeError不正确的测试。


如果你正在寻找一个通用安全的方式代码,一个永远不会出错复制类似阵列的主机对象为实际的数组,然后使用实际阵列阵列操作。 这是保证安全。 有一个跨浏览器的填充工具Array.prototype.slice与复印所有浏览器为实际的数组中的()MDN页.slice 。 如果你只支持IE 9,你不需要填充工具。

而且,人们不应该认为是改变了阵列状物体的任何操作一般是在主机对象上安全的(有可能是特定的例外,但你必须做大量的测试,以确保)。 我的选择是写代码,我知道会是安全的,并不需要大量的测试来保证。 复制到一个实际的数组给了我每一次。



Answer 2:

如果你想确保它会工作,更好地先将其转换为数组。

以类似阵列的对象转换为一个数组,你可以使用ES6 Array.from 。 目前只有火狐32支持它,但有一个填充工具 。

另外, [].slice.call(arrayLike)将大多数浏览器上运行。



文章来源: Portability of Array.prototype.* on array like objects or ever native/host objects