Javascript Array.prototype.*在类似数组的对象或任何本机/主机对象上的可移植性
对于许多Array.prototype函数,ESMA 262 5.1表示它们是有意泛型的,并用对象上的[[Get]]、[[Put]]等操作来描述,但也需要长度属性 因此允许他们处理内置对象,如:Javascript Array.prototype.*在类似数组的对象或任何本机/主机对象上的可移植性,javascript,standards,portability,ecmascript-5,Javascript,Standards,Portability,Ecmascript 5,对于许多Array.prototype函数,ESMA 262 5.1表示它们是有意泛型的,并用对象上的[[Get]]、[[Put]]等操作来描述,但也需要长度属性 因此允许他们处理内置对象,如: obj = {"a":true, "length":10}; Array.prototype.push.call(obj, -1); console.log(obj); // Object { 10: -1, a: true, length: 11 } 对于本机对象,请注意: 推送功能是否能成功应用
obj = {"a":true, "length":10};
Array.prototype.push.call(obj, -1);
console.log(obj); // Object { 10: -1, a: true, length: 11 }
对于本机对象,请注意:
推送功能是否能成功应用
对主机对象的访问依赖于实现
参数是宿主对象吗?似乎所有作为节点列表的DOM都是主机对象。它们在现代浏览器中工作
警告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 如果您想确保它能工作,最好先将其转换为数组 要将类似数组的对象转换为数组,可以使用ES6。目前只有Firefox32支持它,但有一个
或者,[].slice.callarrayLike可以在大多数浏览器上使用。如果您想确保它可以使用,最好先将其转换为数组 要将类似数组的对象转换为数组,可以使用ES6。目前只有Firefox32支持它,但有一个
或者,[].slice.callarrayLike可以在大多数浏览器上使用。由于您从未真正得到完整的答案,我将尝试回答您发布的一些问题 参数是宿主对象吗 参数是Javascript语言的一部分,而不是宿主对象。它有一个定义很好的行为,在严格模式下运行时,该行为已被修改。由于参数不会在当前函数调用之后持续存在,即使在闭包中也不会,而且参数也不是可变的,处理arguments对象的常用方法是立即将一个副本复制到一个实数组中,然后可以在该数组中使用所有常规数组方法,并且可以将其保存在闭包中以供本地函数访问 MDN文档警告
而且,永远不要假设任何更改类似于数组的对象的操作在主机对象上通常是安全的——可能存在特定的异常,但您必须进行大量测试才能确定。我的偏好是编写我知道是安全的代码,并且不需要大量测试来保证安全。每次复制到一个实际的数组中,我都会这样做。因为你从来没有真正得到一个完整的答案,我将尝试回答你发布的一些问题 参数是宿主对象吗 参数是Javascript语言的一部分,而不是宿主对象。它有一个定义很好的行为,在严格模式下运行时,该行为已被修改。由于参数在当前函数调用之后不会持续存在,甚至在闭包中也不会,而且也不意味着它是可变的,因此处理参数的通常方法是 对象是立即将一个副本复制到一个实际数组中,然后可以在该数组中使用所有常规数组方法,并且它可以持久化为一个闭包,以供本地函数访问 MDN文档警告
而且,永远不要假设任何更改类似于数组的对象的操作在主机对象上通常是安全的——可能存在特定的异常,但您必须进行大量测试才能确定。我的偏好是编写我知道是安全的代码,并且不需要大量测试来保证安全。每次复制到一个实际的数组时,我都会这样做。我认为,除非您在所有浏览器和希望支持的浏览器的所有版本中专门测试它们,否则您不能假设任何数组函数都可以在主机对象上工作。特别是,您应该假设如果修改对象(如.push或.splice),它们将不起作用。如果只是将一些元素复制到一个新的数组(如.slice)中,它们更有可能工作。至于node.js,您询问哪些本机对象尚未成为实际数组?响应您的编辑。当且仅当浏览器实际遵循规范时,才会出现TypeError。如果所有浏览器都能完美地遵循所有规范,那么这一切就会容易得多。我坚持我的建议,您必须测试您想要支持的每个浏览器版本/组合。更好的解决方案是立即将任何非数组复制到实际数组中。一般来说,创建副本是一件非常安全的事情,因为所有类似数组的元素都有一个长度,并且通常使用[index]迭代它们,这是创建副本所需的全部。仅供参考,您问题中的第一个代码示例有点无意义。为什么。推入JS对象?你需要一个键和一个值才能成为一个对象的属性。push只提供这个值。这似乎从一开始就不匹配,而且是你永远不应该做甚至尝试去做的事情。@jfriend00:the.push示例并非无稽之谈。.push方法根据对其对象提供的当前.length的分析自动为键提供新索引。例如,这与在jQuery对象上执行相同的操作没有什么不同。@CookieMonester-好的,我明白你的意思。但是,你不会发现我在使用。按非数组。我仍然认为,在非数组对象上使用一系列数组方法的整个推理过程只是一种冒险的编程。如果要对非实际数组的对象执行数组操作,然后将它复制到一个实际的数组中,在这个数组中,你可以拥有完全受支持的方法,而不必考虑什么是有效的,什么是无效的,或者编写你自己的代码,以一种基于你所拥有的对象类型的已知功能可以保证安全的方式来执行操作。我认为你不能假设任何数组都可以运行处理主机对象,除非您在所有浏览器以及希望支持的浏览器的所有版本中专门测试它们。特别地
,您应该假设如果修改对象(如.push或.splice),它们将不起作用。如果只是将一些元素复制到一个新的数组(如.slice)中,它们更有可能工作。至于node.js,您询问哪些本机对象尚未成为实际数组?响应您的编辑。当且仅当浏览器实际遵循规范时,才会出现TypeError。如果所有浏览器都能完美地遵循所有规范,那么这一切就会容易得多。我坚持我的建议,您必须测试您想要支持的每个浏览器版本/组合。更好的解决方案是立即将任何非数组复制到实际数组中。一般来说,创建副本是一件非常安全的事情,因为所有类似数组的元素都有一个长度,并且通常使用[index]迭代它们,这是创建副本所需的全部。仅供参考,您问题中的第一个代码示例有点无意义。为什么。推入JS对象?你需要一个键和一个值才能成为一个对象的属性。push只提供这个值。这似乎从一开始就不匹配,而且是你永远不应该做甚至尝试去做的事情。@jfriend00:the.push示例并非无稽之谈。.push方法根据对其对象提供的当前.length的分析自动为键提供新索引。例如,这与在jQuery对象上执行相同的操作没有什么不同。@CookieMonester-好的,我明白你的意思。但是,你不会发现我在使用。按非数组。我仍然认为,在非数组对象上使用一系列数组方法的整个推理过程只是一种冒险的编程。如果要对非实际数组的对象执行数组操作,然后将它复制到一个实际的数组中,在这个数组中,您拥有完全受支持的方法,对什么有效、什么无效没有任何疑问,或者编写您自己的代码,以一种基于您所拥有的对象类型的已知功能确保安全的方式执行操作。这有什么不同?您使用的正是他询问的概念,以便将其转换为数组,因此您的解决方案受到相同的询问。@CookieMonester和jfriend00一样,仅将元素复制到数组(如slice)中更可能有效。其他修改数组的方法更有可能失败,但在本机对象上也是如此。如果对任何不可变的对象应用变异数组方法,则该对象将失败。他要问的是,通常在宿主对象上使用数组方法是否安全。本机或主机的特定用途超出此点。你最终还是提出了一个回避原始问题的解决方案。这有什么不同?您使用的正是他询问的概念,以便将其转换为数组,因此您的解决方案受到相同的询问。@CookieMonester和jfriend00一样,仅将元素复制到数组(如slice)中更可能有效。其他修改数组的方法更有可能失败,但在本机对象上也是如此。如果对任何不可变的对象应用变异数组方法,则该对象将失败。他要问的是,通常在宿主对象上使用数组方法是否安全。本机或主机的特定用途超出此点。你最终还是提供了一个回避原始问题的解决方案。