popov . dev

Главная

Библиотека

Статьи

Секреты упорядоч...

Секреты упорядочения свойств объектов JavaScript

Недавно мы получили вопрос, обязательно ли свойства объекта JavaScript неупорядочены и непредсказуемы? Разработчики, которые только знакомятся с JavaScript, могут ответить, что Object.keys() или for...in возвращает непредсказуемый порядок свойств объекта. Но так ли это по-прежнему?

Как и следовало ожидать, здесь нет никаких правил, которым нужно следовать.

Начиная с ECMAScript 2020, Object.keys, for...in, Object.getOwnPropertyNames и Reflect.ownKeys следуют одному и тому же порядку спецификации. Они являются:

1. Собственными свойствами являются индексы массива в порядке возрастания числового индекса

const obj = {
    100: 100,
    '2': 2,
    12: 12,
    '0': 0
};

// Результатами будут `[ '0', '2', '12', '100' ]`
console.log(Object.keys(obj));
console.log(Object.getOwnPropertyNemes(obj));
console.log(Reflect.ownKeys(obj));
for (const key in obj) {
    console.log('key:', key);
}

Индекс массива - это ключ свойства, возвращающий значение в виде строки, который представляет собой каноническую числовую строку. А каноническая числовая строка - это строковое представление числа, которое было бы получено с помощью ToString, или строка "-0". Так, например, "012" - это не каноническая числовая строка, а "12".

2. Другие собственные строковые свойства, в хронологическом порядке возрастания создания свойств

const obj = {
    a: 'a'
};

obj.b = 'b';

setTimeout(() => { 
    obj.c = 'c';
});

obj.d = 'd'; 

// Результаты будут следующими '[ 'a', 'b', 'd']`
console.log(Object.keys(obj));
censole.log(Object.getOwnPropertyNames(obj)); console.log(Reflect.ownKeys(obj));

for (const key in obj) {
    console.log('key: ', key);
}

Приведенный выше код добавляет информацию о цикле обработки событий. Поскольку setTimeout является асинхронной макрозадачей, свойство c не было добавлено в obj при использовании консоли.выводится журнал.

3. Собственные свойства символа в хронологическом порядке возрастания создания свойства

const obj = {
    [Symbol('a')]: 'a',
    [Symbol.for('b')]: b;
}

obj[symbol('c')] = 'c'; 
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNemes(obj)); // []
console.log(Reflect.ownkeys(obj)); // [ Symbol(a), Symbol(b), Symbol(c) ]

for (const key in obj) {
    console.log('key: ', key); // Нет вывода 
}

// [ Symbol(a), Symbol(b), Symbol(c) ]
console.log(Object.getOwnPropertySymbols(obj));

Свойство Symbol является таким же, как и свойство String, в хронологическом порядке возрастания создания свойства. Но методы Object.keys, for...in, Object.getOwnPropertyNames не могут получить свойства символов объекта, а Reflect.ownKeys и Object.getOwnPropertySymbols могут.

Заключение

Когда ключи свойств объекта представляют собой комбинацию из перечисленных выше типов, сначала в массив добавляются неотрицательные целочисленные ключи объекта (перечисляемые и неперечисляемые) в порядке возрастания, затем в порядке вставки добавляются строковые ключи. Наконец, символьные ключи добавляются в порядке вставки.

const onj = {
    100: 100,
    0: 0,
    a: 'a',
    [Symbol('a')]: 'a'
};

obj[Symbol.for('b')]: 'b';
obj.b = 'b';

console.log(Object.keys(obj)); // [ '0', '100', 'a', 'b' ]
console.log(Object.getOwnPropertyNames(obj)); // [ '0', '100', 'a', 'b' ]
console.log(Object.ownKeys(obj)); // [ '0', '100', 'a', 'b', Symbol(a), Symbol(b) ]

for (const key in obj) {
    console.log('key: ', key); // '0' '100' 'a' 'b'
}

// [ Symbol(a), Symbol(b) ]
console.log(Object.getOwnPropertyNames(obj));

Но если вы сильно зависите от порядка вставки, то Map вам это гарантирует.

Комментарии

Для того чтобы оставить свое мнение, необходимо зарегистрироваться на сайте