Какие методы есть у объекта в JavaScript?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#JavaScript #Объекты #База JS

Краткий ответ

Методы объектов в JavaScript — это встроенные функции, которые позволяют получать информацию об объектах, манипулировать их свойствами и контролировать их поведение.

Основные группы методов:

  • Object.keys() — получить массив ключей объекта
  • Object.values() — получить массив значений объекта
  • Object.entries() — получить массив пар [ключ, значение]
  • Object.assign() — скопировать свойства из одного объекта в другой
  • Object.freeze() — заморозить объект (запретить изменения)
  • Object.seal() — запечатать объект (запретить добавление/удаление свойств)

Основные методы для получения данных из объекта

Эти методы позволяют извлечь различную информацию из объекта без его изменения.

Object.keys() — получение всех ключей

Что делает: Возвращает массив всех собственных перечисляемых ключей объекта.

const user = {
  name: "Анна",
  age: 25,
  city: "Москва"
};
 
const keys = Object.keys(user);
console.log(keys); // ["name", "age", "city"]
 
// Практическое применение — подсчёт свойств
console.log(`У пользователя ${Object.keys(user).length} свойства`);

Object.values() — получение всех значений

Что делает: Возвращает массив всех собственных перечисляемых значений объекта.

const user = {
  name: "Анна",
  age: 25,
  city: "Москва"
};
 
const values = Object.values(user);
console.log(values); // ["Анна", 25, "Москва"]
 
// Практическое применение — поиск в значениях
const hasAdult = Object.values(user).some(value => 
  typeof value === 'number' && value >= 18
);
console.log(hasAdult); // true

Object.entries() — получение пар ключ-значение

Что делает: Возвращает массив массивов, где каждый внутренний массив содержит [ключ, значение].

const user = {
  name: "Анна",
  age: 25,
  city: "Москва"
};
 
const entries = Object.entries(user);
console.log(entries); 
// [["name", "Анна"], ["age", 25], ["city", "Москва"]]
 
// Практическое применение — создание строки описания
const description = Object.entries(user)
  .map(([key, value]) => `${key}: ${value}`)
  .join(', ');
console.log(description); // "name: Анна, age: 25, city: Москва"

Методы для копирования и объединения объектов

Эти методы позволяют создавать новые объекты на основе существующих или объединять несколько объектов в один.

Object.assign() — поверхностное копирование

Что делает: Копирует все перечисляемые собственные свойства из одного или нескольких источников в целевой объект. Возвращает изменённый целевой объект.

const target = { a: 1 };
const source = { b: 2, c: 3 };
 
// Копирование в существующий объект
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }
 
// Создание нового объекта (рекомендуемый способ)
const newObj = Object.assign({}, target, source);
console.log(newObj); // { a: 1, b: 2, c: 3 }
 
// Практическое применение — объединение настроек
const defaultSettings = { theme: 'light', language: 'ru' };
const userSettings = { theme: 'dark' };
const finalSettings = Object.assign({}, defaultSettings, userSettings);
console.log(finalSettings); // { theme: 'dark', language: 'ru' }

Важно: Object.assign() делает поверхностную копию. Вложенные объекты остаются связанными!

const original = { user: { name: 'Анна' } };
const copy = Object.assign({}, original);
copy.user.name = 'Борис';
console.log(original.user.name); // 'Борис' — изменился и оригинал!

Spread оператор (…) — современная альтернатива

Что делает: Современный способ копирования и объединения объектов, более читаемый чем Object.assign().

const user = { name: 'Анна', age: 25 };
const address = { city: 'Москва', street: 'Тверская' };
 
// Объединение объектов
const fullUser = { ...user, ...address };
console.log(fullUser); 
// { name: 'Анна', age: 25, city: 'Москва', street: 'Тверская' }
 
// Обновление свойств
const updatedUser = { ...user, age: 26, email: 'anna@mail.com' };
console.log(updatedUser); 
// { name: 'Анна', age: 26, email: 'anna@mail.com' }

Object.create() — создание с прототипом

Что делает: Создаёт новый объект с указанным прототипом и свойствами.

// Создание объекта с прототипом
const personPrototype = {
  greet() {
    return `Привет, я ${this.name}`;
  }
};
 
const user = Object.create(personPrototype);
user.name = 'Анна';
user.age = 25;
 
console.log(user.greet()); // 'Привет, я Анна'
 
// Создание объекта без прототипа (чистый словарь)
const cleanObj = Object.create(null);
cleanObj.data = 'значение';
// У cleanObj нет методов toString, hasOwnProperty и т.д.

Методы проверки свойств

1. hasOwnProperty()

const user = { name: "Анна", age: 25 };
 
console.log(user.hasOwnProperty('name')); // true
console.log(user.hasOwnProperty('toString')); // false (наследованное)
 
// Безопасная проверка
console.log(Object.prototype.hasOwnProperty.call(user, 'name')); // true

2. Оператор in

const user = { name: "Анна", age: 25 };
 
console.log('name' in user); // true
console.log('toString' in user); // true (наследованное)
console.log('email' in user); // false
 
// Проверка на undefined
console.log(user.name !== undefined); // true
console.log(user.email !== undefined); // false

3. Object.hasOwn() (ES2022)

const user = { name: "Анна", age: 25 };
 
// Современная альтернатива hasOwnProperty
console.log(Object.hasOwn(user, 'name')); // true
console.log(Object.hasOwn(user, 'toString')); // false

Методы дескрипторов свойств

1. Object.defineProperty()

const user = {};
 
Object.defineProperty(user, 'name', {
  value: 'Анна',
  writable: true,     // можно изменять
  enumerable: true,   // появляется в циклах
  configurable: true  // можно удалять и изменять дескриптор
});
 
// Создание геттера и сеттера
Object.defineProperty(user, 'fullName', {
  get() {
    return `${this.firstName} ${this.lastName}`;
  },
  set(value) {
    [this.firstName, this.lastName] = value.split(' ');
  },
  enumerable: true,
  configurable: true
});
 
user.firstName = "Анна";
user.lastName = "Иванова";
console.log(user.fullName); // "Анна Иванова"

2. Object.defineProperties()

const user = {};
 
Object.defineProperties(user, {
  name: {
    value: 'Анна',
    writable: true,
    enumerable: true
  },
  age: {
    value: 25,
    writable: true,
    enumerable: true
  },
  id: {
    value: 123,
    writable: false,
    enumerable: false
  }
});

3. Object.getOwnPropertyDescriptor()

const user = { name: "Анна" };
 
const descriptor = Object.getOwnPropertyDescriptor(user, 'name');
console.log(descriptor);
// {
//   value: "Анна",
//   writable: true,
//   enumerable: true,
//   configurable: true
// }

Методы защиты объектов

1. Object.freeze()

const user = { name: "Анна", age: 25 };
 
Object.freeze(user);
 
// Эти операции не будут работать
user.name = "Борис";     // не изменится
user.email = "a@a.com";  // не добавится
delete user.age;         // не удалится
 
console.log(user); // { name: "Анна", age: 25 }
 
// Проверка заморозки
console.log(Object.isFrozen(user)); // true

2. Object.seal()

const user = { name: "Анна", age: 25 };
 
Object.seal(user);
 
// Можно изменять существующие свойства
user.name = "Борис"; // ✅ работает
 
// Нельзя добавлять или удалять
user.email = "a@a.com"; // ❌ не добавится
delete user.age;        // ❌ не удалится
 
console.log(Object.isSealed(user)); // true

3. Object.preventExtensions()

const user = { name: "Анна", age: 25 };
 
Object.preventExtensions(user);
 
// Можно изменять и удалять существующие
user.name = "Борис"; // ✅ работает
delete user.age;     // ✅ работает
 
// Нельзя добавлять новые
user.email = "a@a.com"; // ❌ не добавится
 
console.log(Object.isExtensible(user)); // false

Задачи для практики

Задача 1

const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
 
console.log(Object.keys(obj));
console.log(Object.getOwnPropertyNames(obj));
Ответ ['a'] и ['a', 'b'] — Object.keys() возвращает только перечисляемые свойства, а Object.getOwnPropertyNames() все собственные свойства.

Задача 2

const original = { a: { b: 1 } };
const copy1 = Object.assign({}, original);
const copy2 = { ...original };
 
copy1.a.b = 2;
console.log(original.a.b);
console.log(copy2.a.b);
Ответ 2 и 2 — Object.assign() и spread оператор создают поверхностную копию. Вложенные объекты остаются связанными.

Задача 3

const obj = { x: 1, y: 2 };
Object.freeze(obj);
 
obj.x = 10;
obj.z = 3;
console.log(obj);
 
const nested = { a: { b: 1 } };
Object.freeze(nested);
nested.a.b = 2;
console.log(nested.a.b);
Ответ { x: 1, y: 2 } и 2 — Object.freeze() не позволяет изменять свойства первого уровня, но не защищает вложенные объекты.

Лучшие практики

✅ Рекомендации

// 1. Используйте const для объектов
const config = { apiUrl: '...' };
 
// 2. Используйте деструктуризацию
const { name, age } = user;
 
// 3. Используйте Object.hasOwn() вместо hasOwnProperty()
if (Object.hasOwn(obj, 'property')) { /* ... */ }
 
// 4. Создавайте объекты без прототипа для словарей
const dict = Object.create(null);
 
// 5. Используйте Object.assign() или spread для поверхностного копирования
const copy = { ...original };
 
// 6. Используйте Object.freeze() для неизменяемых объектов
const constants = Object.freeze({ PI: 3.14159 });

❌ Чего избегать

// ❌ Изменение Object.prototype
Object.prototype.newMethod = function() {}; // Загрязняет глобальное пространство
 
// ❌ Использование for...in без проверки hasOwnProperty
for (const key in obj) {
  console.log(obj[key]); // Может включать наследованные свойства
}
 
// ❌ Прямое обращение к hasOwnProperty
obj.hasOwnProperty('prop'); // Может не работать если obj.hasOwnProperty перезаписан
 
// ❌ Мутация объектов-аргументов
function updateUser(user) {
  user.lastLogin = new Date(); // Изменяет исходный объект
}
 
// ❌ Использование Object() как конструктора
const obj = new Object(); // Лучше: {}

Частые ошибки

1. Поверхностное vs глубокое копирование

// ❌ Ожидание глубокого копирования
const original = { user: { name: 'Анна' }, items: [1, 2, 3] };
const copy = { ...original };
copy.user.name = 'Борис'; // Изменяет original!
 
// ✅ Правильное глубокое копирование
const deepCopy = JSON.parse(JSON.stringify(original)); // Простой способ
// или
const deepCopy2 = structuredClone(original); // Современный способ

2. Неправильная проверка существования свойств

// ❌ Может дать ложный результат
if (obj.prop) { /* ... */ } // false для 0, "", false, null
 
// ✅ Правильные способы
if (Object.hasOwn(obj, 'prop')) { /* ... */ }
if ('prop' in obj) { /* ... */ }
if (obj.prop !== undefined) { /* ... */ }

3. Мутация во время итерации

// ❌ Проблема
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
  if (obj[key] === 2) {
    delete obj[key]; // Может пропустить элементы
  }
}
 
// ✅ Решение
const keysToDelete = [];
for (const key in obj) {
  if (obj[key] === 2) {
    keysToDelete.push(key);
  }
}
keysToDelete.forEach(key => delete obj[key]);

Резюме

Методы объектов — это мощные инструменты для работы с данными в JavaScript:

Основные категории:

  • Получение данных: Object.keys(), Object.values(), Object.entries()
  • Создание и копирование: Object.create(), Object.assign(), spread operator
  • Проверка свойств: Object.hasOwn(), in, hasOwnProperty()
  • Защита объектов: Object.freeze(), Object.seal(), Object.preventExtensions()
  • Дескрипторы: Object.defineProperty(), Object.getOwnPropertyDescriptor()

Современные возможности:

  • Object.fromEntries() — создание объекта из массива пар
  • Optional chaining — безопасный доступ к свойствам
  • structuredClone() — глубокое клонирование
  • Object.hasOwn() — современная альтернатива hasOwnProperty

Применение:

  • ✅ Манипуляция данными
  • ✅ Валидация и очистка
  • ✅ Создание конфигураций
  • ✅ Реализация паттернов

Понимание методов объектов — это ключ к эффективной работе с данными в JavaScript!


Хочешь больше статей по подготовке к собеседованию? Подпишись на EasyAdvice, добавляй сайт в избранное и прокачивай себя каждый день 💪