Javascript 中的排序属性被破坏

Kar*_*.ma 15 javascript

我需要遍历一个 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);}
Run Code Online (Sandbox Code Playgroud)

输出是:

4294966111
4294966222
4294966333
---
4294968222
4294968333
4294968111
Run Code Online (Sandbox Code Playgroud)

意思是:

  • (test1) 如果keys低于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 的行为与以相同方式排序的三个时间戳不同。

Cer*_*nce 4

这是预料之中的。根据规范,迭代属性的方法OrdinaryOwnPropertyKeys执行以下操作:

\n\n
\n
    \n
  1. 对于作为数组索引的O 的每个自己的属性键 P ,按升序数字索引顺序,执行

    \n\n

    A。添加 P 作为键的最后一个元素。

  2. \n
  3. 对于 O 的每个自己的属性键 P(它是字符串但不是数组索引),按照属性创建的升序时间顺序,执行以下操作:

    \n\n

    A。添加 P 作为键的最后一个元素。

  4. \n
\n
\n\n

升序数字顺序适用于作为数组索引的属性。

\n\n

那么,什么是“数组索引”?查一下::

\n\n
\n

整数索引是一个字符串值属性键,它是一个规范的数字字符串(请参阅 7.1.21),其数值为 +0 或正整数 \xe2\x89\xa4 2^53 - 1。数组索引为一个整数索引,其数值 i 的范围为 +0 \xe2\x89\xa4 i < 2^32 - 1。

\n
\n\n

因此,大于 2^32 的数字属性不是数组索引,因此按照属性创建的顺序进行迭代。但是,小于的数字属性2^32 数组索引,并且按升序数字顺序迭代。

\n\n

因此,例如:

\n\n

1:数组索引,将按数字进行迭代

\n\n

10:数组索引,将按数字进行迭代

\n\n

4294968111:大于,将在数组索引完成2 ** 32按照属性创建顺序进行迭代

\n\n

9999999999999:大于,将在数组索引完成2 ** 32按照属性创建顺序进行迭代

\n\n

另外,请记住,与普遍的看法相反,由于第四阶段的for-in 迭代提案,属性迭代顺序也由规范保证。

\n