Как добавить числовое свойство в объект в JavaScript
Что проверяют
Вопрос с подвохом: ждут не obj.count = 5, а разговора о том, что происходит с числовым ключом. Проверяют, знаете ли вы, что ключи обычных объектов это строки или символы, и как это влияет на порядок и сравнение. Следом часто спрашивают, чем здесь лучше Map.
Как отвечать
Если речь о числовом значении, способов несколько: точка obj.age = 30, скобки obj[key] = 30 для динамического имени, spread { ...obj, age: 30 } для иммутабельного обновления состояния в React, Object.defineProperty. Интереснее числовой ключ:
- приведение к строке:
obj[1] = "a"создаёт свойство"1", поэтомуobj[1]иobj["1"]это одно и то же.obj[1.0]тоже попадёт в"1"; - только скобки:
obj.1это синтаксическая ошибка, идентификатор не может начинаться с цифры; - порядок обхода: ключи, похожие на индексы массива, идут первыми по возрастанию, затем строковые в порядке добавления, затем символы. Добавленный последним ключ
"2"окажется в началеObject.keys; - тип при чтении:
Object.keysиfor...inвозвращают строки, иkeys.includes(1)дастfalse; Map: хранит ключ1как число, сохраняет порядок вставки и не смешивает1с"1".
Про Object.defineProperty добавьте, что неуказанные флаги writable, enumerable и configurable равны false: свойство не видно в Object.keys и JSON.stringify, а запись в него в строгом режиме бросает TypeError. В TypeScript словарь с числовыми ключами описывают как Record<number, T>, но в рантайме ключи всё равно строки.
Где спотыкаются
Пишут obj[someName] и путают переменную со строкой. Если someName не объявлена, получают ReferenceError, а не новое свойство.
Рассчитывают на порядок вставки для числовых ключей и удивляются, что { b: 1, 2: 1, 1: 1 } перечисляется как 1, 2, b.
Считают, что const запрещает менять объект. Он запрещает только переприсваивать переменную, для защиты свойств нужен Object.freeze.