Object.create() создаёт новый объект с указанным прототипом.
Это главный смысл метода: здесь важно не просто создание объекта, а именно то, от какого прототипа он будет наследоваться.
Синтаксис
Object.create(proto)
Object.create(proto, propertiesObject)
proto - объект, который станет прототипом нового объекта.
propertiesObject - необязательный объект с дескрипторами свойств.
Что делает Object.create()
Метод создаёт новый объект и сразу привязывает к нему указанный прототип.
const animal = {
speak() {
console.log("sound");
},
};
const dog = Object.create(animal);
dog.speak(); // "sound"
У dog нет собственного метода speak, но он получает его через прототип.
Прототип нового объекта
Это самое важное в Object.create().
const animal = { type: "animal" };
const dog = Object.create(animal);
console.log(dog.type); // "animal"
console.log(Object.getPrototypeOf(dog) === animal); // true
То есть animal становится прототипом для dog.
Object.create() и обычный объект
Если передать обычный объект как прототип, новый объект будет наследоваться от него.
const base = { kind: "base" };
const obj = Object.create(base);
console.log(obj.kind); // "base"
Но важно помнить, что это не то же самое, что литерал {}:
const a = {};
const b = Object.create({});
Во втором случае у объекта будет свой отдельный прототип, который вы создали вручную.
Object.create(null)
Очень важный случай - создать объект вообще без прототипа.
const dict = Object.create(null);
console.log(Object.getPrototypeOf(dict)); // null
Такой объект:
- не наследуется от
Object.prototype - не имеет методов вроде
toString() - часто используется как простое хранилище ключ-значение
Пример:
const dict = Object.create(null);
dict.name = "Anna";
console.log(dict.name); // "Anna"
Почему это может быть полезно
У обычного объекта есть наследуемые свойства и методы.
У объекта без прототипа их нет:
const normal = {};
const plain = Object.create(null);
console.log("toString" in normal); // true
console.log("toString" in plain); // false
Это бывает полезно, когда объект используется как словарь и не хочется случайных пересечений с наследуемыми свойствами.
propertiesObject и дескрипторы
Вторым аргументом можно сразу описать свойства нового объекта.
const user = Object.create(Object.prototype, {
name: {
value: "Anna",
writable: true,
enumerable: true,
configurable: true,
},
});
console.log(user.name); // "Anna"
Это работает через дескрипторы свойств, как и Object.defineProperty().
Почему второй аргумент используют не так часто
Хотя возможность полезная, в обычном коде чаще пишут проще:
const user = Object.create(Object.prototype);
user.name = "Anna";
Или вообще используют литерал объекта:
const user = { name: "Anna" };
Поэтому второй аргумент чаще встречается в более специфичных случаях.
Object.create() и {}
Для обычного создания объекта литерал {} почти всегда проще:
const user = {};
Object.create() обычно выбирают тогда, когда:
- важен конкретный прототип
- нужен объект без прототипа
- нужно явно работать через прототипное наследование
Object.create() и new Object()
new Object() создаёт обычный объект.
Object.create() позволяет точнее управлять его прототипом.
const a = new Object();
const b = Object.create(null);
console.log(Object.getPrototypeOf(a) === Object.prototype); // true
console.log(Object.getPrototypeOf(b)); // null
Поэтому это методы для разных задач.
Object.create() не копирует объект
Если передать объект как прототип, новый объект не станет его копией.
const animal = { type: "animal" };
const dog = Object.create(animal);
console.log(dog.type); // "animal"
console.log(dog.hasOwnProperty("type")); // false
Свойство type здесь наследуется через прототип, а не хранится как собственное свойство dog.
Когда это полезно
Object.create() удобно использовать, когда:
- нужно создать объект с конкретным прототипом
- нужен объект без прототипа через
Object.create(null) - вы работаете с прототипным наследованием напрямую
Пример:
const person = {
greet() {
console.log(`Привет, я ${this.name}`);
},
};
const user = Object.create(person);
user.name = "Anna";
user.greet(); // "Привет, я Anna"
Частые ошибки
Думать, что Object.create(obj) делает копию
const base = { role: "admin" };
const user = Object.create(base);
console.log(user.role); // "admin"
Это не копия объекта base, а новый объект с base в прототипе.
Забывать, что у Object.create(null) нет методов Object.prototype
const dict = Object.create(null);
// dict.toString(); // Ошибка
Такой объект устроен специально проще.
Путать собственные и наследуемые свойства
const base = { value: 1 };
const obj = Object.create(base);
console.log(obj.value); // 1
console.log(obj.hasOwnProperty("value")); // false
Значение доступно, но оно пришло из прототипа.
Быстрая памятка
Object.create()создаёт объект с указанным прототипомObject.create(null)создаёт объект без прототипа- второй аргумент позволяет задавать свойства через дескрипторы
- метод не копирует переданный объект, а использует его как прототип
- для обычного объекта чаще используют литерал
{}
Коротко
Object.create() - это способ явно управлять прототипом нового объекта. Главное, что стоит запомнить: метод особенно полезен для объектов без прототипа и для случаев, где важно именно наследование, а не просто создание {}.