Skip to main content

Способи створення об'єкта

У JavaScript об'єкт можна створити щонайменше десятьма способами, від літерала {} до Object.fromEntries(). Вибір залежить від того, чи потрібен шаблон із методами, чи явний прототип, чи просто копія наявних даних.

Теорія

TL;DR

  • Об'єктний літерал {} це найчитабельніший і найчастіший спосіб.
  • new Object() робить те саме, але виглядає застаріло і майже не використовується.
  • Функція-конструктор із new і class створюють об'єкти «за шаблоном», class це синтаксичний цукор над функцією.
  • Фабрична функція просто повертає об'єкт, без new і без прототипного спадкування.
  • Object.create(proto) задає прототип явно.
  • JSON.parse(), Object.assign(), spread { ...obj } і Object.fromEntries() створюють об'єкт із готових даних.

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

javascript
const user = { name: 'Oleh', age: 25, isAdmin: false }; // властивості можна додавати і видаляти динамічно user.city = 'Kyiv'; delete user.isAdmin; console.log(user); // { name: 'Oleh', age: 25, city: 'Kyiv' }

Літерал і new Object()

Об'єктний літерал це найпростіший і найпоширеніший спосіб:

javascript
const user = { name: 'Oleh', age: 25, isAdmin: false };

Той самий результат через конструктор:

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

new Object() робить рівно те саме, що {}, але довше і виглядає «по-старому», тому зараз майже не використовується.

Шаблони: функція-конструктор і class

До появи class об'єкти «за шаблоном» створювали саме функцією-конструктором:

javascript
function User(name, age) { this.name = name; this.age = age; } const oleh = new User('Oleh', 25); const alice = new User('Alice', 30); console.log(oleh.name); // "Oleh"

Коли функцію викликають із new, рушій під капотом:

  1. створює порожній об'єкт {};
  2. присвоює його this;
  3. повертає цей об'єкт (якщо функція явно не повернула інший).

class з ES6 це той самий механізм, але зручніший синтаксис:

javascript
class User { constructor(name, age) { this.name = name; this.age = age; } sayHi() { console.log(`Привіт, я ${this.name}`); } } const oleh = new User('Oleh', 25); oleh.sayHi(); // "Привіт, я Oleh"

Методи класу живуть у User.prototype, тобто одна копія методу на всі екземпляри.

Фабрична функція і Object.create()

Замість class чи new можна просто повернути об'єкт:

javascript
function createUser(name, age) { return { name, age, sayHi() { console.log(`Привіт, ${this.name}`); } }; } const oleh = createUser('Oleh', 25); oleh.sayHi(); // "Привіт, Oleh"

Дуже зручний спосіб, особливо коли не потрібні prototype і спадкування. Мінус у тому, що кожен екземпляр отримує власну копію методу.

Object.create() створює новий об'єкт із вказаним прототипом:

javascript
const person = { greet() { console.log(`Привіт, я ${this.name}`); } }; const user = Object.create(person); user.name = 'Oleh'; user.greet(); // "Привіт, я Oleh"

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

Створення з готових даних

З рядка JSON, типовий випадок для відповіді сервера:

javascript
const json = '{"name": "Oleh", "age": 25}'; const user = JSON.parse(json); console.log(user.name); // "Oleh"

Працює тільки з простими типами даних, методи через JSON не передаються.

Object.assign() створює об'єкт на основі інших, копіюючи властивості:

javascript
const base = { a: 1 }; const extra = { b: 2 }; const result = Object.assign({}, base, extra); console.log(result); // { a: 1, b: 2 }

Spread-синтаксис робить те саме коротше і є сучасним стандартом копіювання та об'єднання:

javascript
const user = { name: 'Oleh', age: 25 }; const copy = { ...user, city: 'Kyiv' }; console.log(copy); // { name: 'Oleh', age: 25, city: 'Kyiv' }

Object.fromEntries() збирає об'єкт із масиву пар [ключ, значення]:

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

Що обирати

СпосібПрикладОсобливості
Об'єктний літерал{ name: 'Oleh' }найчастіший спосіб
new Object()new Object()рідко використовується
Функція-конструкторfunction User() { this.name = ... }стара альтернатива class
classclass User { ... }сучасний ООП-підхід
Фабрична функціяfunction createUser() { return {...} }без this, просто повертає об'єкт
Object.create(proto)Object.create(person)створює об'єкт із заданим прототипом
JSON.parse()JSON.parse('{"a":1}')створює об'єкт із рядка
Object.assign()Object.assign({}, obj1, obj2)копіює та зливає об'єкти
Spread-синтаксис{ ...obj1, ...obj2 }короткий синтаксис копіювання
Object.fromEntries()Object.fromEntries([['a', 1]])з масиву пар в об'єкт

Коротко: найпопулярніший спосіб це {}, для спадкування Object.create(), для шаблонів class або функція-конструктор, для копіювання { ...obj } чи Object.assign().

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

  • Виклик функції-конструктора без new. У звичайному режимі this вкаже на глобальний об'єкт і засмітить його, у strict mode буде TypeError.
  • Очікувати глибоку копію від spread чи Object.assign(). Обидва копіюють поверхнево: вкладені об'єкти лишаються спільними. Для глибокої копії беріть structuredClone().
  • Використовувати JSON.parse(JSON.stringify(obj)) як універсальний клон. Втрачаються функції, undefined, Date перетворюється на рядок, а циклічні посилання кидають помилку.
  • Плутати Object.create(proto) і new. Перше просто ставить прототип, друге ще й виконує конструктор.
  • Створювати методи у фабричній функції для тисяч об'єктів. Кожен екземпляр отримує власну копію функції, тоді як class тримає одну в прототипі.
  • Використовувати звичайний {} як словник для довільних ключів. Ключі на кшталт __proto__ або toString конфліктують із прототипом, безпечніші Object.create(null) або Map.

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

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

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