Почему метод Object.fromEntries ведет себя неожиданным способом?

Столкнулся со странным поведением метода Object.fromEntries

Есть следующий код:

const obj = { 0: 6, 1: 7, 2: 8, 3: 3, 4: 4, 5: 5, 6: 0, 7: 1, 8: 2 };

const res = Object.fromEntries(
    Object.entries(obj)
        .map( ([key, value]) => [value, +key] )
);

console.log(JSON.stringify(res) === JSON.stringify(obj)); // true

/*
    obj { 0: 6, 1: 7, 2: 8, 3: 3, 4: 4, 5: 5, 6: 0, 7: 1, 8: 2 }
    res { 0: 6, 1: 7, 2: 8, 3: 3, 4: 4, 5: 5, 6: 0, 7: 1, 8: 2 }
*/

Только вот объект, ссылка на который находится в переменной res, тот-же самый, что и исходный

Может кто-нибудь объяснить что тут происходит? В спецификации про это информации не нашел. Спасибо!


Ответы (1 шт):

Автор решения: Grundy

Ключи и значения в объекте подобраны так, что при обмене их между собой - список ключей и список значений не меняется.

Фактически, вся проверка зависит от того, каким способом по свойствам проходит JSON.stringify при составлении строки.


Обратимся к спецификации: при вызове JSON.stringify без параметров replacer и space все сводится к выполнению внутренней функции SerializeJSONProperty в которую передается текущее состояние, ключ с которого начинается сериализация (пустая строка, аргумент key) и объект заглушка (аргумент holder) представляющий из себя

{
    "": value
}

где value - это объект переданный в JSON.stringify.

В функции SerializeJSONProperty, согласно правилам, в случае, если holder[key] является объектом выполнение переходит в SerializeJSONObject

Здесь, в пункте 5 и 6 определяется порядок обхода свойств. Для случая в вопросе, список свойств не задан, поэтому порядок определяется в функции EnumerableOwnPropertyNames, который составляет список ключей, основываясь на выдаче от [[OwnPropertyKeys]] (подробнее алгоритм можно увидеть в ответе на вопрос По какому принципу цикл FOR IN обходит массив?

Для случая в вопросе: обход производится по числовым ключам в порядке возрастания. Так как список ключей одинаковый, то и результаты также одинаковые.

→ Ссылка