Объект (object) в JavaScript — это значение, которое хранит набор свойств «ключ — значение»: ключ — строка (или Symbol), значение — что угодно, включая функцию. А Object с большой буквы — встроенный конструктор, у которого есть статические методы для работы с любыми объектами: Object.keys, Object.values, Object.entries, Object.assign, Object.freeze и другие.
Содержание
- Три значения слова Object
- Как создать объект в JavaScript
- Object.keys, Object.values, Object.entries
- Object.assign и копирование объекта
- Object.freeze и Object.seal: защита от изменений
- Частые ошибки с объектами
- Сводка статических методов Object
- Object в Java: коротко
- Выводы
- Где применяется / связь с практикой
- FAQ
В Java слово Object значит третье — корневой класс java.lang.Object, от которого наследуются все классы. Ниже разбираем JavaScript: как создать объект, как читать и менять свойства, что делают основные методы Object и на каких ошибках спотыкаются новички. В конце — короткая справка по Java. Все примеры прогнаны в Node.js 24.21 (24.09.2026).
Три значения слова Object
Путаница начинается с того, что одним словом называют разные вещи. Разведем их сразу.
| Термин | Что это | Пример |
|---|---|---|
| объект в JS (значение) | коллекция свойств «ключ — значение» | { name: "Анна", age: 28 } |
Object в JS (конструктор) |
встроенная функция со статическими методами-утилитами | Object.keys(user) |
java.lang.Object |
корневой класс Java, его методы есть у каждого объекта | obj.equals(other), obj.hashCode() |
Важная граница: методы вроде Object.keys вызываются на самом Object, а объект передается аргументом. Записи user.keys() не существует — будет ошибка user.keys is not a function.
Как создать объект в JavaScript
Самый частый способ — литерал в фигурных скобках. Полный пример: создаем объект, читаем, добавляем и удаляем свойства, проверяем наличие ключа и перебираем пары.
// 1. Литерал объекта - самый частый способ
const user = {
name: "Анна",
age: 28,
"last-login": "2026-09-20",
greet() {
return `Привет, я ${this.name}`;
},
};
console.log(user.name); // точечная нотация
console.log(user["last-login"]); // скобки: для ключей с дефисом и вычисляемых имен
console.log(user.greet());
user.city = "Казань"; // добавить свойство
delete user.age; // удалить свойство
console.log("age" in user, Object.hasOwn(user, "city"));
// 2. Статические методы Object
console.log(Object.keys(user));
console.log(Object.values(user).length);
for (const [key, value] of Object.entries(user)) {
if (typeof value !== "function") console.log(`${key} = ${value}`);
}
Результат в консоли:
Анна
2026-09-20
Привет, я Анна
false true
[ 'name', 'last-login', 'greet', 'city' ]
4
name = Анна
last-login = 2026-09-20
city = Казань
Что здесь важно:
constзапрещает переприсвоить переменнуюuser, но не запрещает менять сам объект — поэтомуuser.city = ...работает. Запрет изменений делаетObject.freeze(ниже).- Точка работает для ключей-идентификаторов, скобки — для ключей с дефисом, пробелом или хранящихся в переменной:
user[fieldName]. "age" in userищет свойство и в цепочке прототипов,Object.hasOwn(user, "city")— только собственные свойства. Для словарей обычно нужен второй вариант.
Другие способы создания встречаются реже: new Object() делает то же, что {}, но длиннее; Object.create(proto) создает объект с заданным прототипом; class и функции-конструкторы нужны, когда объектов одного вида много. Прототипы и классы — отдельная большая тема, здесь на них не останавливаемся.
Object.keys, Object.values, Object.entries
Три метода превращают объект в массив, а с массивом уже работают map, filter, reduce:
Object.keys(obj)— массив ключей;Object.values(obj)— массив значений;Object.entries(obj)— массив пар[ключ, значение].
Обратную операцию делает Object.fromEntries — собирает объект из пар. Связка entries -> map -> fromEntries — стандартный способ «пройтись по объекту и получить новый объект».
const prices = { apple: 120, pear: 95, plum: 80 };
// entries -> map -> fromEntries: скидка 10% на все
const discounted = Object.fromEntries(
Object.entries(prices).map(([name, price]) => [name, Math.round(price * 0.9)])
);
console.log(discounted);
// сумма значений
const total = Object.values(prices).reduce((sum, p) => sum + p, 0);
console.log(total);
// порядок ключей: сначала индексы массива по возрастанию, потом строки в порядке добавления
const mixed = { b: 1, 10: "x", a: 2, 2: "y" };
console.log(Object.keys(mixed));
{ apple: 108, pear: 86, plum: 72 }
295
[ '2', '10', 'b', 'a' ]
Последняя строка показывает правило порядка: ключи-индексы массива (целые от 0 до 2^32-2 в канонической записи) идут первыми по возрастанию и становятся строками, остальные строковые ключи — в порядке добавления. Граница правила: "-1", "1.5" и "01" похожи на числа, но индексами не считаются и стоят среди обычных строк в порядке добавления. Все три метода возвращают только собственные перечисляемые свойства со строковыми ключами: унаследованные свойства и Symbol-ключи в результат не попадают.
Object.assign и копирование объекта
Object.assign(target, ...sources) копирует собственные перечисляемые свойства из источников в target и возвращает target. Если ключ встречается несколько раз, побеждает последний источник. Типичное применение — настройки по умолчанию плюс пользовательские.
const defaults = { theme: "light", lang: "ru", notify: { email: true, sms: false } };
const saved = { lang: "en", notify: { sms: true } };
const settings = Object.assign({}, defaults, saved);
console.log(settings);
// поверхностная копия: вложенный объект общий
const copy = Object.assign({}, defaults);
copy.notify.email = false;
console.log(defaults.notify.email);
// глубокая копия
const defaults2 = { theme: "light", notify: { email: true } };
const deep = structuredClone(defaults2);
deep.notify.email = false;
console.log(defaults2.notify.email);
// spread - то же, что assign в новый объект
console.log({ ...defaults, ...saved }.lang);
{ theme: 'light', lang: 'en', notify: { sms: true } }
false
true
en
Здесь две ловушки, и обе видны в выводе.
Первая: слияние неглубокое. Вложенный notify из saved целиком заменил notify из defaults, и поле email пропало. Для вложенных настроек сливать нужно каждый уровень отдельно.
Вторая: копия поверхностная. copy.notify и defaults.notify — один и тот же объект, поэтому правка копии испортила оригинал (false во второй строке). Глубокую копию дает structuredClone — он есть в Node.js начиная с 17-й версии и в современных браузерах, но не копирует функции (на объекте с методом бросит DataCloneError). Пустой объект {} первым аргументом нужен, чтобы не испортить исходник: Object.assign(defaults, saved) изменит сам defaults.
Object.freeze и Object.seal: защита от изменений
Object.freeze(obj) запрещает добавлять, удалять и менять свойства. Object.seal(obj) запрещает добавлять и удалять, но существующие значения менять можно. Object.preventExtensions(obj) запрещает только добавление.
"use strict";
const config = Object.freeze({ port: 8080, db: { host: "localhost" } });
try {
config.port = 3000;
} catch (e) {
console.log(e.constructor.name + ": " + e.message);
}
config.db.host = "10.0.0.5"; // вложенный объект не заморожен
console.log(config.port, config.db.host, Object.isFrozen(config), Object.isFrozen(config.db));
function deepFreeze(obj) {
for (const value of Object.values(obj)) {
if (value !== null && typeof value === "object") deepFreeze(value);
}
return Object.freeze(obj);
}
const cfg = deepFreeze({ port: 8080, db: { host: "localhost" } });
try { cfg.db.host = "x"; } catch (e) { console.log(e.constructor.name); }
const sealed = Object.seal({ a: 1 });
sealed.a = 2;
try { sealed.b = 3; } catch (e) { console.log(e.constructor.name + ": " + e.message); }
console.log(sealed);
TypeError: Cannot assign to read only property 'port' of object '#<Object>'
8080 10.0.0.5 true false
TypeError
TypeError: Cannot add property b, object is not extensible
{ a: 2 }
Поведение зависит от режима. В строгом режиме ("use strict", ES-модули, тело class) запись в замороженный объект бросает TypeError. В нестрогом скрипте та же запись молча игнорируется: config.port = 3000 не изменит значение и не выдаст ошибку. Поэтому баг «значение не поменялось» при заморозке без строгого режима искать труднее.
freeze тоже поверхностный: config.db остался изменяемым. Функция deepFreeze выше рекурсивно замораживает вложенные объекты; она рассчитана на обычные данные без циклических ссылок.
| Метод | Добавить | Удалить | Изменить значение | Проверка |
|---|---|---|---|---|
Object.preventExtensions |
нет | да | да | Object.isExtensible |
Object.seal |
нет | нет | да | Object.isSealed |
Object.freeze |
нет | нет | нет | Object.isFrozen |
Частые ошибки с объектами
Сравнение через ===. Оператор сравнивает ссылки, а не содержимое.
const a = { id: 1 };
const b = { id: 1 };
console.log(a === b); // разные объекты
console.log(a === a);
console.log(JSON.stringify(a) === JSON.stringify(b));
console.log(Object.is(NaN, NaN), NaN === NaN, Object.is(0, -0));
const dict = Object.create(null);
dict.toString = "ok";
console.log(Object.keys(dict), "toString" in {});
false
true
true
true false false
[ 'toString' ] true
Два одинаковых по виду объекта не равны: это разные значения в памяти. Сравнение через JSON.stringify работает только в простых случаях: { a: 1, b: 2 } и { b: 2, a: 1 } дадут false из-за разного порядка ключей, а функции и undefined при сериализации теряются. Для надежного сравнения пишут функцию, которая обходит ключи, или берут готовую из библиотеки. Object.is отличается от === только для NaN и -0, содержимое объектов он тоже не сравнивает.
Object.create(null) дает объект без прототипа — чистый словарь, где ключ toString не конфликтует с унаследованным методом. Обычный {} уже «содержит» toString через прототип, что видно по "toString" in {}. Если нужен словарь с произвольными ключами, часто удобнее Map.
Чтение свойства у несуществующего вложенного объекта. Неверный код и результат:
const user = { name: "Анна" };
console.log(user.age); // нет такого свойства
console.log(user.address?.city);
try {
console.log(user.address.city);
} catch (e) {
console.log(e.constructor.name + ": " + e.message);
}
undefined
undefined
TypeError: Cannot read properties of undefined (reading 'city')
Отсутствующее свойство возвращает undefined без ошибки, но обращение к полю у undefined падает. Исправление — опциональная цепочка user.address?.city: она возвращает undefined, если address нет. Текст ошибки приведен для Node.js (движок V8); в Firefox и Safari формулировка другая.
Сводка статических методов Object
| Метод | Что делает | Возвращает |
|---|---|---|
Object.keys(obj) |
собственные перечисляемые ключи | массив строк |
Object.values(obj) |
значения этих ключей | массив |
Object.entries(obj) |
пары ключ — значение | массив [key, value] |
Object.fromEntries(pairs) |
объект из пар или Map |
новый объект |
Object.assign(target, ...src) |
копирует свойства в target |
target |
Object.freeze(obj) / Object.seal(obj) |
запрет изменений (поверхностно) | тот же obj |
Object.hasOwn(obj, key) |
есть ли собственное свойство | true / false |
Object.create(proto) |
объект с заданным прототипом | новый объект |
Object.is(a, b) |
строгое равенство с учетом NaN и -0 |
true / false |
Object в Java: коротко
В Java java.lang.Object — суперкласс всех классов. Его методы есть у любого объекта: equals, hashCode, toString, getClass, а также wait/notify/notifyAll для синхронизации потоков и clone (работает только для классов, реализующих Cloneable). Метод finalize объявлен устаревшим с Java 9, а с Java 18 (JEP 421) помечен к удалению (forRemoval); в Java 25 он еще есть, но в новом коде его не используют — ресурсы закрывают через AutoCloseable и try-with-resources.
Главная практическая связка — equals и hashCode: по умолчанию equals сравнивает ссылки, как === в JavaScript, а коллекции HashSet/HashMap опираются на оба метода. Их переопределяют вместе:
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class Main {
static class Point {
final int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
}
static class GoodPoint {
final int x, y;
GoodPoint(int x, int y) { this.x = x; this.y = y; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GoodPoint p)) return false;
return x == p.x && y == p.y;
}
@Override
public int hashCode() { return Objects.hash(x, y); }
}
public static void main(String[] args) {
Point a = new Point(1, 2), b = new Point(1, 2);
System.out.println(a.equals(b));
Set<Point> set = new HashSet<>(Set.of(a));
System.out.println(set.contains(b));
GoodPoint c = new GoodPoint(1, 2), d = new GoodPoint(1, 2);
System.out.println(c.equals(d) + " " + (c == d));
System.out.println(new HashSet<>(Set.of(c)).contains(d));
}
}
false
false
true false
true
Запуск: java Main.java (Java 25, однофайловый режим). Без переопределения точки с одинаковыми координатами не равны и не находятся в HashSet; после — равны по содержимому, хотя == по-прежнему сравнивает ссылки. Подробнее про классы и объекты в Java — в статье Java для новичков: что нужно знать о class и object.
Выводы
- Объект в JavaScript — набор свойств «ключ — значение»;
Object— встроенный конструктор со статическими методами;java.lang.Objectв Java — корневой класс. Это три разные сущности. Object.keys,values,entriesпревращают объект в массив,Object.fromEntriesсобирает обратно; порядок ключей: сначала индексы массива (неотрицательные целые) по возрастанию, затем строки в порядке добавления.Object.assignи spread копируют поверхностно, вложенные объекты остаются общими; для глубокой копии данных естьstructuredClone.Object.freezeтоже поверхностный и бросаетTypeErrorтолько в строгом режиме, в нестрогом запись молча игнорируется.===сравнивает ссылки, а не содержимое объектов — и в JavaScript, и (через==иequalsпо умолчанию) в Java.
Где применяется / связь с практикой
Объекты — основа почти любого JavaScript-кода: ответы API в JSON, настройки, состояние интерфейса во фронтенд-фреймворках, параметры функций. Методы Object нужны каждый день, когда надо перебрать данные, слить настройки или защитить конфигурацию от случайной правки.
Освойте тему на практике
Если хотите системно пройти основы языка — объекты, массивы, функции, асинхронность и работу с DOM — посмотрите курс «JavaScript-разработчик. Базовый уровень». Разобрать отдельные темы с преподавателями можно на открытых уроках Otus.
FAQ
Чем Object отличается от Map в JavaScript?
Map принимает ключи любого типа (объекты, числа без приведения к строке), хранит порядок вставки для всех ключей, знает размер через size и не имеет унаследованных ключей. Обычный объект удобнее для записей с заранее известными полями и для JSON.
Почему typeof null возвращает «object»?
Это историческая ошибка первой реализации языка, которую сохранили ради совместимости. Проверять объект надежнее условием value !== null && typeof value === "object", как в deepFreeze выше.
Массив — это тоже объект?
Да, typeof [] вернет "object", а Object.keys(["a", "b"]) даст ['0', '1']. Отличить массив от обычного объекта помогает Array.isArray.



