我需要循环遍历一个 JavaScript 对象,将其视为具有自定义键的数组。 我知道这并没有得到完全支持,因为属性没有内在顺序,但由于我总是对属性重新排序,所以我发现这种方法简单可靠......直到现在。
当键是数字或可以转换为数字的字符串时,就会出现问题。
当我运行此代码时:
var test1 = {4294966222:"A",4294966333:"A",4294966111:"A"};
var test2 = {4294968222:"A",4294968333:"A",4294968111:"A"};
for (var k in test1) {console.log(k);}
console.log("---");
for (var k in test2) {console.log(k);}
输出是:
4294966111
4294966222
4294966333
---
4294968222
4294968333
4294968111
这意味着:
- (test1)如果键小于 2^32 (4,294,967,296),它们会自动重新排序,最小的在前
- (test2)如果键大于 2^32,则不会重新排序。
问题是:为什么会发生这种情况?
由于我测试的所有浏览器(Google Chrome 79.0、Mozilla Firefox 71.0、Microsoft Edge 44.18362、Internet Explorer 11.535)都同意此输出,因此必须有一些官方规范。
更新
在发现这是一个阈值问题之前,我测试了很多数字。我发现奇怪的是序列 2,3,1 的行为与以相同方式排序的三个时间戳不同。
最佳答案
这是预期的。根据 specification ,迭代属性的方法 OrdinaryOwnPropertyKeys
的作用是:
For each own property key P of O that is an array index, in ascending numeric index order, do
a. Add P as the last element of keys.
For each own property key P of O that is a String but is not an array index, in ascending chronological order of property creation, do
a. Add P as the last element of keys.
升序数字顺序仅适用于作为数组索引的属性。
那么,什么是“数组索引”? Look it up: :
An integer index is a String-valued property key that is a canonical numeric String (see 7.1.21) and whose numeric value is either +0 or a positive integer ≤ 2^53 - 1. An array index is an integer index whose numeric value i is in the range +0 ≤ i < 2^32 - 1.
因此,大于 2^32 的数字属性不是数组索引,因此按照属性创建的顺序进行迭代。但是,小于 2^32
的数字属性是数组索引,并按升序数字顺序迭代。
例如:
1
:数组索引,将按数字进行迭代
10
:数组索引,将按数字进行迭代
4294968111
:大于2 ** 32
,将在数组索引完成后按属性创建顺序迭代
9999999999999
:大于2 ** 32
,将在数组索引完成后按属性创建顺序迭代
此外,请记住,与普遍的看法相反,属性迭代顺序也由规范保证,这要归功于 for-in iteration proposal这是第 4 阶段。
关于javascript - Javascript 中的排序属性已损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59407858/