为什么不将“9007199254740991”视为整数索引?

Why is not "9007199254740991" treated as an integer index?

根据 the specification,数值为 2 ** 53 - 1 的字符串值 属性 键必须被视为整数索引。 根据 the specification[[OwnPropertyKeys]] 内部方法必须枚举 属性 键,这是一个整数索引,按数字升序排列。 根据the specificationReflect.ownKeys调用[[OwnPropertyKeys]]内部方法。

所以,如果我的理解是正确的,下面的代码应该按数字升序显示 属性 键(即 ["9007199254740990", "9007199254740991"])。 然而,所有现有的实现都以 属性 创建的升序时间顺序显示 属性 键(即 ["9007199254740991", "9007199254740990"])。

console.log(Reflect.ownKeys({"9007199254740991": null, "9007199254740990": null}));

我的错误是什么?

9007199254740991是JavaScript中的最大安全整数。

var x = Number.MAX_SAFE_INTEGER + 1,
  y = Number.MAX_SAFE_INTEGER + 2,
  z = Number.MAX_SAFE_INTEGER + 3,
  i = Number.MAX_SAFE_INTEGER + 4,
  j = Number.MAX_SAFE_INTEGER + 5;

console.log("max: "+Number.MAX_SAFE_INTEGER);
// expected output: 9007199254740991
// real output:     9007199254740991

console.log("x:   "+x);
// expected output: 9007199254740992
// real output:     9007199254740992

console.log("y:   "+y);
// expected output: 9007199254740993
// real output:     9007199254740992

console.log("z:   "+z);
// expected output: 9007199254740994
// real output:     9007199254740994

console.log("i:   "+i);
// expected output: 9007199254740995
// real output:     9007199254740996

console.log("j:   "+j);
// expected output: 9007199254740996
// real output:     9007199254740996

有些行为符合预期。

阅读以下内容:

  1. MDN web docs > Number.MAX_SAFE_INTEGER
  2. What is JavaScript's highest integer value that a number can go to without losing precision?

所以我们知道:

bitwise operators and shift operators operate on 32-bit ints, so in that case, the max safe integer is 231-1, or 2147483647.

我不知道 Reflect.ownKeys() 如何将索引按数字顺序排序。
由于以下代码段:

const objs = [
    // does not work
    {
        9007199254740991: null,
        9007199254740990: null,
    },
    // works
    {
        2147483648: null,
        // max save bitwise number
        2147483647: null,
    },
    // works
    {
        4294967295: null,
        // max save bitwise number times 2
        4294967294: null,
    },
    // does not work
    {
        5368709118: null,
        // max save bitwise number times 2.5
        5368709117: null,
    }
];

const objkeys = [],
    max = objs.length;

for (let i = 0; i < max; i++) {
    objkeys.push(Reflect.ownKeys(objs[i]))
}

for (let i = 0; i < max; i++) {
    console.log(objkeys[i][0]+" < "+objkeys[i][1]);
}

我希望你对 9007199254740991 和 JavaScript

有所了解

The specification of the [[OwnPropertyKeys]] internal method in ECMAScript 2017 (and in 2018) did not match the real behavior of all major JavaScript engines, so in ECMAScript 2019, the specification has been fixed。 参见 the discussion on GitHub