Создание объекта в JavaScript: применение new и .apply()
Быстрый ответ
Чтобы вызвать конструктор с массивом аргументов, воспользуйтесь методом Reflect.construct()
:
function MyConstructor(...args) {
this.sum = args.reduce((acc, val) => acc + val, 0);
}
const args = [1, 2, 3];
const obj = Reflect.construct(MyConstructor, args);
console.log(obj.sum); // Радость общения! Сумма равна 6! 🎉
Reflect.construct()
— это современный метод из ES6, предназначенный для передачи аргументов в конструктор, что напоминает принцип работы функции .apply()
. Оба они зачастую используются совместно, но не являются идентичными сущностями!
Осваиваем работу с переменным количеством аргументов
[AsideBanner]
В нашем арсенале — Function.prototype.bind
Если вам требуется создавать объекты с произвольным числом аргументов, на помощь придёт Function.prototype.bind
:
function SpecialConstructor(...) {
// Здесь некоторая логика конструктора
}
const obj = new (Function.prototype.bind.apply(
SpecialConstructor, [null].concat(args)));
// И вуаля! Перед нами образовался новый объект!
Оставайтесь начеку! Проверьте, не был ли до вас модифицирован метод bind
.
Создание объекта Date
легко и просто
Предположим, что мы работаем с конструктором Date
в JavaScript, который критичен к аргументам:
function MyDate(year, month, day) {
return new Date(year, month, day);
}
const boundConstructor = MyDate.bind(null, 2021, 11);
const myDateInstance = new boundConstructor(17);
// Мы практически мгновенно переместились во времени: 17 ноября 2021 года. 😎
Безопасное взаимодействие с TypeScript
Тем, кто использует TypeScript и не хочет столкнуться с проблемами из-за неправильного возвращаемого типа, рекомендуется указать void
:
function Constructible<F extends new (...args: any) => any>(constructor: F): void {
// Функция ничего не возвращает, пропустите её без стеснения.
}
Знакомимся с оператором расширения
Если вы хотите сделать ваш JavaScript код более автономным и эффективным, используйте оператор расширения ES6 (...
) для передачи аргументов:
const parts = ['2021', '11', '17'];
const date = new Date(...parts);
// Вот перед нами свежесозданная дата — словно выброшенная из временной капсулы!
Не забудьте удостовериться, что ваша среда выполнения JavaScript корректно обрабатывает оператор расширения и поддерживает его использование.
Новый, яркий и блестящий — Reflect.construct()
Пришло время познакомиться со свежим инструментом из семейства функций ES6: Reflect.construct()
— стильным и элегантным:
const args = [/* список аргументов */];
const obj = Reflect.construct(MyConstructor, args);
// И вот перед вами чудо — новый экземпляр объекта! 💥
Ощутите наслаждение от создания объектов с использованием разнообразных аргументов этим новым способом!
Визуализация
Пора сделать паузу и выпить чаю. Вообразим, что метод .apply()
— это Мэри Поппинс в мире JavaScript:
let keys = [engineKey, doorsKey, colorKey];
let car = Car.bind.apply(Car, [null].concat(keys));
// Вот и Мэри Поппинс, .apply() окутывает и объединяет всё воедино! 🌂
Изящный способ создания объектов
Упакуйте логику создания объекта, избегая прямого обращения к new
и this
:
function construct(F, args) {
return new (Function.prototype.bind.apply(F, [null].concat(args)));
// Ваш новый объект готов, сэр. Почувствуйте волшебство .apply()!
}
Джентльменам больше по душе классы
Если вам кажется, что работа с прототипами вышла из моды, попробуйте использовать изящный Object.create(), когда вам это будет нужно:
function ChildClass() {
ParentClass.apply(this, arguments);
}
ChildClass.prototype = Object.create(ParentClass.prototype);
// И теперь все достоинства ParentClass переданы ChildClass.
Полезные материалы
- Function.prototype.apply() – JavaScript | MDN — Детальное руководство по использованию
.apply()
в JavaScript. - javascript – Use of .apply() with 'new' operator. Is this possible? – Stack Overflow — Обсуждения и решения вопросов о применении
.apply()
сnew
. - new – JavaScript | MDN — Официальное описание оператора
new
в JavaScript. - Spread syntax (...) – JavaScript | MDN — Оператор расширения в JavaScript.
- Reflect.construct() – JavaScript | MDN — Описание работы метода
Reflect.construct()
. - Function.prototype.bind() – JavaScript | MDN — Все об использовании метода
.bind()
для предварительной установки аргументов.