Объекты и прототипы
Объект в JavaScript — это набор свойств, где каждое свойство описано не только значением, но и скрытым дескриптором: флагами writable, enumerable, configurable. От этих флагов зависит, можно ли свойство переписать, увидит ли его перечисление и получится ли его удалить. Большинство свойств вы создаёте обычным присваиванием и не замечаете дескрипторы — пока не столкнётесь с тем, что метод класса не попадает в Object.keys, а замороженный объект молча игнорирует запись.
Эта тема разбирает механику самих объектов: как их создают, как устроены дескрипторы и аксессоры, в каком порядке перечисляются ключи и почему копирование по умолчанию поверхностное. Прототипную цепочку — как объекты наследуют друг от друга — выносим в отдельную тему Прототипы и наследование. Полная карта — в слоях ниже.
Карта темы
- Создание объектов — литерал
{},Object.create, конструктор сnewиclass, а также вычисляемые имена свойств. - Дескрипторы свойств — флаги
writable/enumerable/configurable,definePropertyиgetOwnPropertyDescriptor. - Свойства-аксессоры —
get/setвместо хранимого значения — вычисление на чтении и проверка на записи. - Перечисление свойств —
Object.keys/values/entriesпротивfor...in, флагenumerableи почему методы класса невидимы. - Порядок свойств — целочисленные ключи по возрастанию, затем строковые в порядке вставки, затем символы.
- Копирование объектов — поверхностная копия (
spread,Object.assign) против глубокой (structuredClone) и ловушка общей ссылки.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Считать {...o} глубокой копией | Вложенные объекты общие по ссылке — мутация видна в оригинале |
Ждать метод класса в Object.keys | Методы на прототипе неперечисляемы, их там нет |
Итерировать объект через for...in без hasOwnProperty | В цикл попадут унаследованные свойства из прототипа |
| Рассчитывать на порядок вставки для числовых ключей | Целочисленные ключи всегда идут первыми по возрастанию, а не как вставлены |
Присваивать значение свойству, созданному только с get | Тихо игнорируется (или бросает в strict): у аксессора нет set |
Думать, что Object.freeze защищает вложенные объекты | Заморозка поверхностная — внутренний объект остаётся мутабельным |
Значение для собеседований
Объекты спрашивают, чтобы проверить, понимаете ли вы разницу между значением и ссылкой и знаете ли, что свойство — это не просто «ключ и значение», а запись с флагами. Кандидат, который на вопрос про копирование сразу говорит «spread копирует один уровень, вложенное остаётся общим по ссылке», выглядит увереннее того, кто путает копию с клоном.
Что обычно проверяют:
- Способы создания объекта и чем
Object.create(proto)отличается от литерала. - Что такое дескриптор и какие флаги в нём; зачем
defineProperty. - Почему
for...inвидит унаследованное, аObject.keys— нет. - Порядок перечисления ключей и почему
{2:'a',1:'b'}даёт1,2. - Поверхностная против глубокой копии и что делает
structuredClone.
Типичный неверный ответ: «Object.assign делает глубокую копию». На самом деле это поверхностная копия одного уровня — вложенные объекты и массивы остаются общими по ссылке, и мутация через одну сторону видна в другой.