Skip to main content

Object.create()

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

Теорія

TL;DR

  • Синтаксис: Object.create(proto, [propertiesObject]).
  • proto стає [[Prototype]] нового об'єкта, перевірити можна через Object.getPrototypeOf().
  • Другий аргумент задає власні властивості у форматі дескрипторів, як у Object.defineProperty().
  • Object.create(null) створює об'єкт зовсім без прототипу, зручний для словників.
  • Це найпростіший спосіб прототипного наслідування без class і конструкторів.
  • Новий об'єкт не копіює властивості прототипу, він лише посилається на нього.

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

javascript
const user = { sayHi() { console.log(`Привіт, ${this.name}!`); } }; const alice = Object.create(user); // об'єкт, що успадковує від user alice.name = 'Alice'; alice.sayHi(); // "Привіт, Alice!"

Тут user є прототипом ([[Prototype]]) для alice. Власного методу sayHi в alice немає, він успадкований через прототип.

Синтаксис і параметри

javascript
Object.create(proto, [propertiesObject])
ПараметрОпис
protoОб'єкт, який стане прототипом нового об'єкта (або null)
propertiesObject (необов'язковий)Додаткові власні властивості у форматі дескрипторів

Перевірити результат можна так:

javascript
console.log(Object.getPrototypeOf(alice) === user); // true

Object.create() буквально створює новий об'єкт, чий прихований [[Prototype]] дорівнює user.

Об'єкт без прототипу

javascript
const data = Object.create(null); data.a = 1; console.log(data); // { a: 1 } console.log(Object.getPrototypeOf(data)); // null console.log(data.toString); // undefined

Такий об'єкт не успадковує нічого, навіть toString чи hasOwnProperty. Його використовують як чистий словник (map-об'єкт), де ключі приходять ззовні і не повинні конфліктувати з іменами методів Object.prototype. Мінус лише один: перевіряти наявність ключа доведеться через Object.hasOwn(data, key) або 'a' in data.

Другий аргумент: дескриптори властивостей

Властивості можна одразу задати з атрибутами, як у Object.defineProperty():

javascript
const person = Object.create({}, { name: { value: 'Alice', writable: false, enumerable: true }, age: { value: 25, writable: true } }); console.log(person.name); // "Alice" person.name = 'Bob'; // не змінить значення console.log(person.name); // "Alice"

Другий параметр приймає ті самі атрибути: value, writable, enumerable, configurable, а також get і set. Пам'ятайте, що пропущені атрибути тут теж дорівнюють false, тому age з прикладу не буде видно в Object.keys().

Прототипне наслідування без класів

Найпряміший спосіб зробити «наслідування» вручну:

javascript
const Animal = { eat() { console.log('Я їм'); } }; const Dog = Object.create(Animal); Dog.bark = function() { console.log('Гав!'); }; Dog.eat(); // "Я їм", успадковано від Animal Dog.bark(); // "Гав!", власний метод

Той самий підхід замінює class, якщо створення екземпляра винести в метод ініціалізації:

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

Такий стиль часто застосовують у функціональному ООП: без класів, але з наслідуванням через прототип.

Підсумок:

Що робитьПрикладРезультат
Створює об'єкт із заданим прототипомObject.create(proto)Новий об'єкт, у якого [[Prototype]] = proto
Створює об'єкт без прототипуObject.create(null)«Чистий» об'єкт без toString і hasOwnProperty
Задає властивості з атрибутамиObject.create({}, { key: { value: 1 } })Аналог defineProperty()
Реалізує наслідуванняconst child = Object.create(parent)child успадковує властивості parent

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

  • Плутати прототип із копією. Object.create(proto) не копіює властивості: якщо змінити proto пізніше, зміни побачить і нащадок.
  • Шукати успадковані ключі в Object.keys(). Там лише власні властивості, а for...in навпаки обійде і прототипні, тому в циклах потрібен Object.hasOwn().
  • Викликати методи Object.prototype на об'єкті з Object.create(null). data.hasOwnProperty('a') кине TypeError; правильно Object.hasOwn(data, 'a') або Object.prototype.hasOwnProperty.call(data, 'a').
  • Забувати про дефолтні false у другому аргументі. Властивість, створена через propertiesObject без явних атрибутів, не змінюється і не перелічується.
  • Записувати в успадковану властивість і чекати зміни прототипу. Присвоєння створює власну властивість у нащадка і просто затуляє прототипну (shadowing), а не змінює її.

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

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

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