Skip to main content

Способи оголосити об'єкт

У JavaScript є кілька способів створити об'єкт, і вибір залежить від того, що саме потрібно: простий об'єкт, копія, шаблон чи екземпляр класу. Усі вони дають той самий тип даних, але відрізняються тим, як задається прототип і скільки шаблонного коду доводиться писати.

Теорія

TL;DR

  • Літерал {} це найкоротший і найчастіший спосіб у реальному коді.
  • new Object() робить те саме, але довше, тому його майже не використовують.
  • Object.create(proto) створює об'єкт із заданим прототипом.
  • Функція-конструктор з new і class створюють екземпляри певного «типу».
  • Spread ({ ...base }) створює копію наявного об'єкта з новими властивостями.
  • Object.fromEntries() збирає об'єкт із пар «ключ -> значення».

Швидкий приклад

javascript
const user = { name: 'Tim', age: 25 };

Літерал створює новий об'єкт одразу з потрібними властивостями. Це найпоширеніший спосіб у реальному коді: коротко, читабельно і без зайвих церемоній.

Літерал і конструктор Object

Через конструктор той самий об'єкт виглядає так:

javascript
const user = new Object(); user.name = 'Tim'; user.age = 25;

Спосіб робочий, але зазвичай не рекомендований: літерали ({}) коротші й зрозуміліші, а результат виходить ідентичним. new Object() зустрічається хіба що в старому коді або заради сумісності.

Object.create(proto)

Цей спосіб дозволяє створити об'єкт із визначеним прототипом:

javascript
const person = { species: 'human' }; const user = Object.create(person); user.name = 'Tim'; console.log(user.species); // "human" (успадковано від person)

Його використовують у просунутих сценаріях, коли потрібно вручну керувати ланцюжком прототипів. Окремий корисний випадок це Object.create(null): об'єкт зовсім без прототипу, зручний як словник.

Функція-конструктор і class

Функції-конструктори (виклик з new) створюють об'єкти певного «типу» і автоматично встановлюють this на новий об'єкт:

javascript
function User(name, age) { this.name = name; this.age = age; } const tim = new User('Tim', 25); console.log(tim.name); // "Tim"

class це синтаксичний цукор над функцією-конструктором, і саме його використовують у сучасному JS:

javascript
class User { constructor(name, age) { this.name = name; this.age = age; } } const tim = new User('Tim', 25); console.log(tim.name); // "Tim"

Обидва варіанти дають екземпляри зі спільним прототипом, тому методи зберігаються один раз, а не копіюються в кожен об'єкт.

Spread і Object.fromEntries()

Spread створює копію наявного об'єкта з додаванням нових властивостей:

javascript
const base = { role: 'user' }; const user = { ...base, name: 'Tim', age: 25 };

Object.fromEntries() збирає об'єкт із масиву пар, що корисно після Object.entries() або під час роботи з Map:

javascript
const entries = [['name', 'Tim'], ['age', 25]]; const user = Object.fromEntries(entries); console.log(user); // { name: 'Tim', age: 25 }

Підсумкова таблиця

СпосібПрикладКоли використовувати
Літерал {}{ name: 'Tim' }найчастіший спосіб
new Object()new Object()рідко, заради сумісності
Object.create(proto)Object.create(person)потрібне керування прототипом
Функція-конструкторnew User()старий, але робочий підхід
classnew User()сучасний, ООП-підхід
Spread, копія{ ...obj }дублювання і розширення об'єктів
Object.fromEntries()Object.fromEntries(pairs)створення з пар «ключ -> значення»

Якщо стисло: об'єкт у JS можна створити різними способами, від простого {} до class, але у 95% випадків достатньо літерала {} або class для структурованих даних.

Типові помилки

  • Писати new Object() замість {}. Результат той самий, але коду більше, а читабельності менше.
  • Плутати Object.create(person) з копіюванням. Властивості person не копіюються, вони успадковуються, тому зміна прототипу відразу видно в усіх нащадках.
  • Викликати функцію-конструктор без new. Тоді this не буде новим об'єктом, функція поверне undefined, а в нестрогому режимі ще й зіпсує глобальний об'єкт.
  • Вважати { ...base } глибокою копією. Spread копіює тільки верхній рівень, вкладені об'єкти залишаються спільними.
  • Чекати від spread копіювання прототипу. Розкладаються лише власні перелічувані властивості, тому екземпляр класу після spread стає звичайним об'єктом без методів.
  • Використовувати звичайний об'єкт як словник для довільних ключів. Ключі на кшталт constructor або toString конфліктують із прототипом; тут доречніші Object.create(null) або Map.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.