Создание объекта в JavaScript: применение new и .apply()

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Чтобы вызвать конструктор с массивом аргументов, воспользуйтесь методом Reflect.construct():

JS
Скопировать код
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(). Оба они зачастую используются совместно, но не являются идентичными сущностями!

Осваиваем работу с переменным количеством аргументов

Кинга Идем в IT: пошаговый план для смены профессии

В нашем арсенале — Function.prototype.bind

Если вам требуется создавать объекты с произвольным числом аргументов, на помощь придёт Function.prototype.bind:

JS
Скопировать код
function SpecialConstructor(...) {
  // Здесь некоторая логика конструктора
}

const obj = new (Function.prototype.bind.apply(
                SpecialConstructor, [null].concat(args)));
// И вуаля! Перед нами образовался новый объект!

Оставайтесь начеку! Проверьте, не был ли до вас модифицирован метод bind.

Создание объекта Date легко и просто

Предположим, что мы работаем с конструктором Date в JavaScript, который критичен к аргументам:

JS
Скопировать код
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:

typescript
Скопировать код
function Constructible<F extends new (...args: any) => any>(constructor: F): void {
  // Функция ничего не возвращает, пропустите её без стеснения.
}

Знакомимся с оператором расширения

Если вы хотите сделать ваш JavaScript код более автономным и эффективным, используйте оператор расширения ES6 (...) для передачи аргументов:

JS
Скопировать код
const parts = ['2021', '11', '17'];
const date = new Date(...parts);
// Вот перед нами свежесозданная дата — словно выброшенная из временной капсулы!

Не забудьте удостовериться, что ваша среда выполнения JavaScript корректно обрабатывает оператор расширения и поддерживает его использование.

Новый, яркий и блестящий — Reflect.construct()

Пришло время познакомиться со свежим инструментом из семейства функций ES6: Reflect.construct() — стильным и элегантным:

JS
Скопировать код
const args = [/* список аргументов */];
const obj = Reflect.construct(MyConstructor, args);
// И вот перед вами чудо — новый экземпляр объекта! 💥

Ощутите наслаждение от создания объектов с использованием разнообразных аргументов этим новым способом!

Визуализация

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Пора сделать паузу и выпить чаю. Вообразим, что метод .apply() — это Мэри Поппинс в мире JavaScript:

JS
Скопировать код
let keys = [engineKey, doorsKey, colorKey];
let car = Car.bind.apply(Car, [null].concat(keys));
// Вот и Мэри Поппинс, .apply() окутывает и объединяет всё воедино! 🌂

Изящный способ создания объектов

Упакуйте логику создания объекта, избегая прямого обращения к new и this:

JS
Скопировать код
function construct(F, args) { 
  return new (Function.prototype.bind.apply(F, [null].concat(args)));
  // Ваш новый объект готов, сэр. Почувствуйте волшебство .apply()!
}

Джентльменам больше по душе классы

Если вам кажется, что работа с прототипами вышла из моды, попробуйте использовать изящный Object.create(), когда вам это будет нужно:

JS
Скопировать код
function ChildClass() {
  ParentClass.apply(this, arguments);
}

ChildClass.prototype = Object.create(ParentClass.prototype);
// И теперь все достоинства ParentClass переданы ChildClass.

Полезные материалы

  1. Function.prototype.apply() – JavaScript | MDN — Детальное руководство по использованию .apply() в JavaScript.
  2. javascript – Use of .apply() with 'new' operator. Is this possible? – Stack Overflow — Обсуждения и решения вопросов о применении .apply() с new.
  3. new – JavaScript | MDN — Официальное описание оператора new в JavaScript.
  4. Spread syntax (...) – JavaScript | MDN — Оператор расширения в JavaScript.
  5. Reflect.construct() – JavaScript | MDN — Описание работы метода Reflect.construct().
  6. Function.prototype.bind() – JavaScript | MDN — Все об использовании метода .bind() для предварительной установки аргументов.