Wrapper / Boxing — Обёртка / Боксинг
Функция-обёртка над функцией или класс-контейнер над значением. В GoF отдельного паттерна нет — это семейство приёмов, близких к Adapter и Decorator.
Проблема
- Добавить поведение к функции (логирование, профилирование, мемоизация) — Wrapper.
- Превратить примитив в объект с валидацией/методами (Email, Phone, Money) — Boxing.
Решение
Wrapper (HOF): функция принимает функцию, возвращает функцию с добавленным поведением.
Boxing: класс или объект, оборачивающий примитив. В JS все примитивы боксированы автоматически ('str'.length работает за счёт автобоксинга в String).
Пример в JS
// Wrapper — функция-обёртка
const wrap = (before, fn, after) =>
(...args) => after(fn(...before(...args)));
const sum = (a, b) => a + b;
const wrapped = wrap(
(a, b) => [a * 2, b * 2],
sum,
(r) => r + 1,
);
wrapped(1, 2); // ((1*2)+(2*2))+1 = 7
// Boxing — класс-контейнер со своей валидацией
class Email {
constructor(value) {
if (!value.includes('@')) throw new Error('invalid email');
this.value = value;
}
domain { return this.value.split('@')[1]; }
}
const e = new Email('test@example.com');
e.domain; // 'example.com'
Где используется в JS-экосистеме
- DDD Value Objects:
Money,Email,PhoneNumber— типичный boxing - Decorators в Node:
util.debuglog(name)возвращает wrapped function - HOF:
_.throttle,_.debounce,_.memoize— wrapper-ы - Autoboxing:
(42).toString()— Number boxing на лету
Подводные камни
- Wrapper теряет
fn.length— обёрнутая функция «не знает», сколько аргументов брала исходная. - Wrapper теряет
fn.name— стек-трейсы становятся менее читаемыми (нужноObject.defineProperty(wrapped, 'name', ...)). - Boxing vs Adapter: Adapter стыкует разные контракты; Boxing просто оборачивает.
- Boxing vs Decorator: Decorator работает с тем же интерфейсом и расширяет; Boxing добавляет интерфейс к примитиву.
Главные тезисы автора
- «Wrapper в GoF нет, но в JS это чуть ли не синоним адаптера».
- Wrapper — это HOF: принимает функцию, возвращает функцию.
before/after-перехватчики — универсальная схема обёртки.- Для async-функций перехватчиков четыре: до вызова, после вызова, до callback, после callback.
- «В JavaScript боксирование везде» — все примитивы боксированы.
- Свой бокс полезен для валидации в конструкторе: телефон, email, адрес.
factorify,poolify,promisify— все построены на идее wrapper.
🎓 Источники
- 🎓 Примеси, обертки, декораторы, мемоизация · 2019-09-28
- Wrapper = HOF
- Универсальный wrapper с before/after
- Async wrapper с 4 перехватчиками
- Потеря fn.length при оборачивании
- 🎓 GoF Patterns Обзор всех паттернов · 2025-04-29
- Boxing — объектная обёртка над скаляром
- В JS все примитивы боксированы
- Свой бокс: телефон, email с валидацией
- 🎓 Адаптер, Декоратор, Прокси, Фасад — В чём разница · 2026-02-09
- Wrapper ≈ адаптер функции в JS